diff mbox series

[PATCHv2,01/12] acpi: Create subtable parsing infrastructure

Message ID 20181211010310.8551-2-keith.busch@intel.com (mailing list archive)
State New, archived
Headers show
Series Heterogeneous memory node attributes | expand

Commit Message

Keith Busch Dec. 11, 2018, 1:02 a.m. UTC
Parsing entries in an ACPI table had assumed a generic header structure
that is most common. There is no standard ACPI header, though, so less
common types would need custom parsers if they want go through their
sub-table entry list.

Create the infrastructure for adding different table types so parsing
the entries array may be more reused for all ACPI system tables.

Signed-off-by: Keith Busch <keith.busch@intel.com>
---
 arch/x86/kernel/acpi/boot.c  | 36 ++++++++++++------------
 drivers/acpi/numa.c          | 16 +++++------
 drivers/acpi/scan.c          |  4 +--
 drivers/acpi/tables.c        | 67 +++++++++++++++++++++++++++++++++++++-------
 drivers/irqchip/irq-gic-v3.c |  2 +-
 drivers/mailbox/pcc.c        |  2 +-
 include/linux/acpi.h         |  5 +++-
 7 files changed, 91 insertions(+), 41 deletions(-)

Comments

Rafael J. Wysocki Dec. 11, 2018, 9:44 a.m. UTC | #1
On Tue, Dec 11, 2018 at 2:05 AM Keith Busch <keith.busch@intel.com> wrote:
>
> Parsing entries in an ACPI table had assumed a generic header structure
> that is most common. There is no standard ACPI header, though, so less
> common types would need custom parsers if they want go through their
> sub-table entry list.

It looks like the problem at hand is that acpi_hmat_structure is
incompatible with acpi_subtable_header because of the different layout
and field sizes.

If so, please state that clearly here.

With that, please feel free to add

Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

to this patch.
kernel test robot Dec. 13, 2018, 9:05 a.m. UTC | #2
Hi Keith,

I love your patch! Yet something to improve:

[auto build test ERROR on pm/linux-next]
[also build test ERROR on v4.20-rc6]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Keith-Busch/acpi-Create-subtable-parsing-infrastructure/20181211-154110
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
config: ia64-allnoconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 8.1.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=8.1.0 make.cross ARCH=ia64 

All errors (new ones prefixed by >>):

   arch/ia64/kernel/acpi.c: In function 'early_acpi_boot_init':
>> arch/ia64/kernel/acpi.c:675:3: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
      acpi_parse_lsapic, NR_CPUS);
      ^~~~~~~~~~~~~~~~~
   In file included from arch/ia64/kernel/acpi.c:43:
   include/linux/acpi.h:250:29: note: expected 'acpi_tbl_entry_handler' {aka 'int (*)(union acpi_subtable_headers *, const long unsigned int)'} but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
         acpi_tbl_entry_handler handler,
         ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
   arch/ia64/kernel/acpi.c: In function 'acpi_boot_init':
   arch/ia64/kernel/acpi.c:718:43: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
         (ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE, acpi_parse_lapic_addr_ovr, 0) < 0)
                                              ^~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from arch/ia64/kernel/acpi.c:43:
   include/linux/acpi.h:250:29: note: expected 'acpi_tbl_entry_handler' {aka 'int (*)(union acpi_subtable_headers *, const long unsigned int)'} but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
         acpi_tbl_entry_handler handler,
         ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
   arch/ia64/kernel/acpi.c:722:59: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
     if (acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0)
                                                              ^~~~~~~~~~~~~~~~~~~~
   In file included from arch/ia64/kernel/acpi.c:43:
   include/linux/acpi.h:250:29: note: expected 'acpi_tbl_entry_handler' {aka 'int (*)(union acpi_subtable_headers *, const long unsigned int)'} but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
         acpi_tbl_entry_handler handler,
         ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
   arch/ia64/kernel/acpi.c:729:32: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
         (ACPI_MADT_TYPE_IO_SAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1) {
                                   ^~~~~~~~~~~~~~~~~~
   In file included from arch/ia64/kernel/acpi.c:43:
   include/linux/acpi.h:250:29: note: expected 'acpi_tbl_entry_handler' {aka 'int (*)(union acpi_subtable_headers *, const long unsigned int)'} but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
         acpi_tbl_entry_handler handler,
         ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
   arch/ia64/kernel/acpi.c:738:40: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
         (ACPI_MADT_TYPE_INTERRUPT_SOURCE, acpi_parse_plat_int_src,
                                           ^~~~~~~~~~~~~~~~~~~~~~~
   In file included from arch/ia64/kernel/acpi.c:43:
   include/linux/acpi.h:250:29: note: expected 'acpi_tbl_entry_handler' {aka 'int (*)(union acpi_subtable_headers *, const long unsigned int)'} but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
         acpi_tbl_entry_handler handler,
         ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
   arch/ia64/kernel/acpi.c:744:42: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
         (ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr, 0) < 0)
                                             ^~~~~~~~~~~~~~~~~~~~~~
   In file included from arch/ia64/kernel/acpi.c:43:
   include/linux/acpi.h:250:29: note: expected 'acpi_tbl_entry_handler' {aka 'int (*)(union acpi_subtable_headers *, const long unsigned int)'} but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
         acpi_tbl_entry_handler handler,
         ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
   arch/ia64/kernel/acpi.c:748:55: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
     if (acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src, 0) < 0)
                                                          ^~~~~~~~~~~~~~~~~~
   In file included from arch/ia64/kernel/acpi.c:43:
   include/linux/acpi.h:250:29: note: expected 'acpi_tbl_entry_handler' {aka 'int (*)(union acpi_subtable_headers *, const long unsigned int)'} but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
         acpi_tbl_entry_handler handler,
         ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
   cc1: some warnings being treated as errors

vim +/acpi_table_parse_madt +675 arch/ia64/kernel/acpi.c

^1da177e4 Linus Torvalds 2005-04-16  660  
62ee0540f Doug Chapman   2008-11-05  661  int __init early_acpi_boot_init(void)
62ee0540f Doug Chapman   2008-11-05  662  {
62ee0540f Doug Chapman   2008-11-05  663  	int ret;
62ee0540f Doug Chapman   2008-11-05  664  
62ee0540f Doug Chapman   2008-11-05  665  	/*
62ee0540f Doug Chapman   2008-11-05  666  	 * do a partial walk of MADT to determine how many CPUs
62ee0540f Doug Chapman   2008-11-05  667  	 * we have including offline CPUs
62ee0540f Doug Chapman   2008-11-05  668  	 */
62ee0540f Doug Chapman   2008-11-05  669  	if (acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
62ee0540f Doug Chapman   2008-11-05  670  		printk(KERN_ERR PREFIX "Can't find MADT\n");
62ee0540f Doug Chapman   2008-11-05  671  		return 0;
62ee0540f Doug Chapman   2008-11-05  672  	}
62ee0540f Doug Chapman   2008-11-05  673  
62ee0540f Doug Chapman   2008-11-05  674  	ret = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC,
62ee0540f Doug Chapman   2008-11-05 @675  		acpi_parse_lsapic, NR_CPUS);
62ee0540f Doug Chapman   2008-11-05  676  	if (ret < 1)
62ee0540f Doug Chapman   2008-11-05  677  		printk(KERN_ERR PREFIX
62ee0540f Doug Chapman   2008-11-05  678  		       "Error parsing MADT - no LAPIC entries\n");
247dba58a Baoquan He     2014-05-05  679  	else
247dba58a Baoquan He     2014-05-05  680  		acpi_lapic = 1;
62ee0540f Doug Chapman   2008-11-05  681  

:::::: The code at line 675 was first introduced by commit
:::::: 62ee0540f5e5a804b79cae8b3c0185a85f02436b [IA64] fix boot panic caused by offline CPUs

:::::: TO: Doug Chapman <doug.chapman@hp.com>
:::::: CC: Tony Luck <tony.luck@intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot Dec. 19, 2018, 10:10 p.m. UTC | #3
Hi Keith,

I love your patch! Yet something to improve:

[auto build test ERROR on pm/linux-next]
[also build test ERROR on v4.20-rc7 next-20181219]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Keith-Busch/acpi-Create-subtable-parsing-infrastructure/20181211-154110
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.2.0 make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

   drivers//irqchip/irq-gic.c: In function 'acpi_gic_redist_is_present':
>> drivers//irqchip/irq-gic.c:1552:10: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
             acpi_dummy_func, 0) > 0;
             ^~~~~~~~~~~~~~~
   In file included from drivers//irqchip/irq-gic.c:36:0:
   include/linux/acpi.h:249:5: note: expected 'acpi_tbl_entry_handler {aka int (*)(union acpi_subtable_headers *, const long unsigned int)}' but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
    int acpi_table_parse_madt(enum acpi_madt_type id,
        ^~~~~~~~~~~~~~~~~~~~~
   drivers//irqchip/irq-gic.c: In function 'gic_v2_acpi_init':
   drivers//irqchip/irq-gic.c:1614:11: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
              gic_acpi_parse_madt_cpu, 0);
              ^~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers//irqchip/irq-gic.c:36:0:
   include/linux/acpi.h:249:5: note: expected 'acpi_tbl_entry_handler {aka int (*)(union acpi_subtable_headers *, const long unsigned int)}' but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
    int acpi_table_parse_madt(enum acpi_madt_type id,
        ^~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   drivers//irqchip/irq-gic-v2m.c: In function 'gicv2m_acpi_init':
>> drivers//irqchip/irq-gic-v2m.c:495:11: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
              acpi_parse_madt_msi, 0);
              ^~~~~~~~~~~~~~~~~~~
   In file included from drivers//irqchip/irq-gic-v2m.c:18:0:
   include/linux/acpi.h:249:5: note: expected 'acpi_tbl_entry_handler {aka int (*)(union acpi_subtable_headers *, const long unsigned int)}' but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
    int acpi_table_parse_madt(enum acpi_madt_type id,
        ^~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   drivers//irqchip/irq-gic-v3.c: In function 'gic_acpi_collect_gicr_base':
>> drivers//irqchip/irq-gic-v3.c:1417:17: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
      redist_parser = gic_acpi_parse_madt_redist;
                    ^
   drivers//irqchip/irq-gic-v3.c: In function 'gic_acpi_count_gicr_regions':
   drivers//irqchip/irq-gic-v3.c:1468:11: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
              gic_acpi_match_gicr, 0);
              ^~~~~~~~~~~~~~~~~~~
   In file included from drivers//irqchip/irq-gic-v3.c:20:0:
   include/linux/acpi.h:249:5: note: expected 'acpi_tbl_entry_handler {aka int (*)(union acpi_subtable_headers *, const long unsigned int)}' but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
    int acpi_table_parse_madt(enum acpi_madt_type id,
        ^~~~~~~~~~~~~~~~~~~~~
   drivers//irqchip/irq-gic-v3.c:1475:11: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
              gic_acpi_match_gicc, 0);
              ^~~~~~~~~~~~~~~~~~~
   In file included from drivers//irqchip/irq-gic-v3.c:20:0:
   include/linux/acpi.h:249:5: note: expected 'acpi_tbl_entry_handler {aka int (*)(union acpi_subtable_headers *, const long unsigned int)}' but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
    int acpi_table_parse_madt(enum acpi_madt_type id,
        ^~~~~~~~~~~~~~~~~~~~~
   drivers//irqchip/irq-gic-v3.c: In function 'gic_acpi_collect_virt_info':
   drivers//irqchip/irq-gic-v3.c:1542:11: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
              gic_acpi_parse_virt_madt_gicc, 0);
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers//irqchip/irq-gic-v3.c:20:0:
   include/linux/acpi.h:249:5: note: expected 'acpi_tbl_entry_handler {aka int (*)(union acpi_subtable_headers *, const long unsigned int)}' but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
    int acpi_table_parse_madt(enum acpi_madt_type id,
        ^~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   drivers//irqchip/irq-gic-v3-its.c: In function 'acpi_table_parse_srat_its':
>> drivers//irqchip/irq-gic-v3-its.c:3812:4: error: passing argument 4 of 'acpi_table_parse_entries' from incompatible pointer type [-Werror=incompatible-pointer-types]
       gic_acpi_match_srat_its, 0);
       ^~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers//irqchip/irq-gic-v3-its.c:18:0:
   include/linux/acpi.h:242:12: note: expected 'acpi_tbl_entry_handler {aka int (*)(union acpi_subtable_headers *, const long unsigned int)}' but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
    int __init acpi_table_parse_entries(char *id, unsigned long table_size,
               ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers//irqchip/irq-gic-v3-its.c:3826:4: error: passing argument 4 of 'acpi_table_parse_entries' from incompatible pointer type [-Werror=incompatible-pointer-types]
       gic_acpi_parse_srat_its, 0);
       ^~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers//irqchip/irq-gic-v3-its.c:18:0:
   include/linux/acpi.h:242:12: note: expected 'acpi_tbl_entry_handler {aka int (*)(union acpi_subtable_headers *, const long unsigned int)}' but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
    int __init acpi_table_parse_entries(char *id, unsigned long table_size,
               ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers//irqchip/irq-gic-v3-its.c: In function 'its_acpi_probe':
>> drivers//irqchip/irq-gic-v3-its.c:3884:10: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
             gic_acpi_parse_madt_its, 0);
             ^~~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers//irqchip/irq-gic-v3-its.c:18:0:
   include/linux/acpi.h:249:5: note: expected 'acpi_tbl_entry_handler {aka int (*)(union acpi_subtable_headers *, const long unsigned int)}' but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
    int acpi_table_parse_madt(enum acpi_madt_type id,
        ^~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   drivers//irqchip/irq-gic-v3-its-platform-msi.c: In function 'its_pmsi_acpi_init':
>> drivers//irqchip/irq-gic-v3-its-platform-msi.c:147:10: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
             its_pmsi_parse_madt, 0);
             ^~~~~~~~~~~~~~~~~~~
   In file included from include/linux/acpi_iort.h:22:0,
                    from drivers//irqchip/irq-gic-v3-its-platform-msi.c:18:
   include/linux/acpi.h:249:5: note: expected 'acpi_tbl_entry_handler {aka int (*)(union acpi_subtable_headers *, const long unsigned int)}' but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
    int acpi_table_parse_madt(enum acpi_madt_type id,
        ^~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors
--
   drivers//irqchip/irq-gic-v3-its-pci-msi.c: In function 'its_pci_acpi_msi_init':
>> drivers//irqchip/irq-gic-v3-its-pci-msi.c:191:10: error: passing argument 2 of 'acpi_table_parse_madt' from incompatible pointer type [-Werror=incompatible-pointer-types]
             its_pci_msi_parse_madt, 0);
             ^~~~~~~~~~~~~~~~~~~~~~
   In file included from include/linux/acpi_iort.h:22:0,
                    from drivers//irqchip/irq-gic-v3-its-pci-msi.c:18:
   include/linux/acpi.h:249:5: note: expected 'acpi_tbl_entry_handler {aka int (*)(union acpi_subtable_headers *, const long unsigned int)}' but argument is of type 'int (*)(struct acpi_subtable_header *, const long unsigned int)'
    int acpi_table_parse_madt(enum acpi_madt_type id,
        ^~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/acpi_table_parse_madt +1552 drivers//irqchip/irq-gic.c

d60fc3892 Tomasz Nowicki 2015-03-24  1548  
f26527b14 Marc Zyngier   2015-09-28  1549  static bool __init acpi_gic_redist_is_present(void)
f26527b14 Marc Zyngier   2015-09-28  1550  {
f26527b14 Marc Zyngier   2015-09-28  1551  	return acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR,
f26527b14 Marc Zyngier   2015-09-28 @1552  				     acpi_dummy_func, 0) > 0;
f26527b14 Marc Zyngier   2015-09-28  1553  }
d60fc3892 Tomasz Nowicki 2015-03-24  1554  

:::::: The code at line 1552 was first introduced by commit
:::::: f26527b1428f379fbd7edf779854c3b41bc0b3e5 irqchip / GIC: Convert the GIC driver to ACPI probing

:::::: TO: Marc Zyngier <Marc.Zyngier@arm.com>
:::::: CC: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Schmauss, Erik Dec. 19, 2018, 11:19 p.m. UTC | #4
> -----Original Message-----
> From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-
> owner@vger.kernel.org] On Behalf Of Rafael J. Wysocki
> Sent: Tuesday, December 11, 2018 1:45 AM
> To: Busch, Keith <keith.busch@intel.com>
> Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>; ACPI Devel
> Maling List <linux-acpi@vger.kernel.org>; Linux Memory Management List
> <linux-mm@kvack.org>; Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>; Rafael J. Wysocki <rafael@kernel.org>;
> Hansen, Dave <dave.hansen@intel.com>; Williams, Dan J
> <dan.j.williams@intel.com>
> Subject: Re: [PATCHv2 01/12] acpi: Create subtable parsing infrastructure
> 
> On Tue, Dec 11, 2018 at 2:05 AM Keith Busch <keith.busch@intel.com>
> wrote:
> >

Hi Rafael and Bob,

> > Parsing entries in an ACPI table had assumed a generic header
> > structure that is most common. There is no standard ACPI header,
> > though, so less common types would need custom parsers if they want go
> > through their sub-table entry list.
> 
> It looks like the problem at hand is that acpi_hmat_structure is incompatible
> with acpi_subtable_header because of the different layout and field sizes.

Just out of curiosity, why don't we use ACPICA code to parse static ACPI tables
in Linux?

We have a disassembler for static tables that parses all supported tables. This
seems like a duplication of code/effort...

Erik
> 
> If so, please state that clearly here.
> 
> With that, please feel free to add
> 
> Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> to this patch.
Dan Williams Dec. 19, 2018, 11:59 p.m. UTC | #5
On Wed, Dec 19, 2018 at 3:19 PM Schmauss, Erik <erik.schmauss@intel.com> wrote:
>
>
>
> > -----Original Message-----
> > From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-
> > owner@vger.kernel.org] On Behalf Of Rafael J. Wysocki
> > Sent: Tuesday, December 11, 2018 1:45 AM
> > To: Busch, Keith <keith.busch@intel.com>
> > Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>; ACPI Devel
> > Maling List <linux-acpi@vger.kernel.org>; Linux Memory Management List
> > <linux-mm@kvack.org>; Greg Kroah-Hartman
> > <gregkh@linuxfoundation.org>; Rafael J. Wysocki <rafael@kernel.org>;
> > Hansen, Dave <dave.hansen@intel.com>; Williams, Dan J
> > <dan.j.williams@intel.com>
> > Subject: Re: [PATCHv2 01/12] acpi: Create subtable parsing infrastructure
> >
> > On Tue, Dec 11, 2018 at 2:05 AM Keith Busch <keith.busch@intel.com>
> > wrote:
> > >
>
> Hi Rafael and Bob,
>
> > > Parsing entries in an ACPI table had assumed a generic header
> > > structure that is most common. There is no standard ACPI header,
> > > though, so less common types would need custom parsers if they want go
> > > through their sub-table entry list.
> >
> > It looks like the problem at hand is that acpi_hmat_structure is incompatible
> > with acpi_subtable_header because of the different layout and field sizes.
>
> Just out of curiosity, why don't we use ACPICA code to parse static ACPI tables
> in Linux?
>
> We have a disassembler for static tables that parses all supported tables. This
> seems like a duplication of code/effort...

Oh, I thought acpi_table_parse_entries() was the common code. What's
the ACPICA duplicate?
Schmauss, Erik Dec. 20, 2018, 1:15 a.m. UTC | #6
> -----Original Message-----
> From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-
> owner@vger.kernel.org] On Behalf Of Dan Williams
> Sent: Wednesday, December 19, 2018 4:00 PM
> To: Schmauss, Erik <erik.schmauss@intel.com>
> Cc: Rafael J. Wysocki <rafael@kernel.org>; Busch, Keith
> <keith.busch@intel.com>; Moore, Robert <robert.moore@intel.com>;
> Linux Kernel Mailing List <linux-kernel@vger.kernel.org>; ACPI Devel
> Maling List <linux-acpi@vger.kernel.org>; Linux Memory Management
> List <linux-mm@kvack.org>; Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>; Hansen, Dave
> <dave.hansen@intel.com>
> Subject: Re: [PATCHv2 01/12] acpi: Create subtable parsing
> infrastructure
> 
> On Wed, Dec 19, 2018 at 3:19 PM Schmauss, Erik
> <erik.schmauss@intel.com> wrote:
> >
> >
> >
> > > -----Original Message-----
> > > From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-
> > > owner@vger.kernel.org] On Behalf Of Rafael J. Wysocki
> > > Sent: Tuesday, December 11, 2018 1:45 AM
> > > To: Busch, Keith <keith.busch@intel.com>
> > > Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>; ACPI
> > > Devel Maling List <linux-acpi@vger.kernel.org>; Linux Memory
> > > Management List <linux-mm@kvack.org>; Greg Kroah-Hartman
> > > <gregkh@linuxfoundation.org>; Rafael J. Wysocki
> <rafael@kernel.org>;
> > > Hansen, Dave <dave.hansen@intel.com>; Williams, Dan J
> > > <dan.j.williams@intel.com>
> > > Subject: Re: [PATCHv2 01/12] acpi: Create subtable parsing
> > > infrastructure
> > >
> > > On Tue, Dec 11, 2018 at 2:05 AM Keith Busch
> <keith.busch@intel.com>
> > > wrote:
> > > >
> >
> > Hi Rafael and Bob,
> >
> > > > Parsing entries in an ACPI table had assumed a generic header
> > > > structure that is most common. There is no standard ACPI
> header,
> > > > though, so less common types would need custom parsers if they
> > > > want go through their sub-table entry list.
> > >
> > > It looks like the problem at hand is that acpi_hmat_structure is
> > > incompatible with acpi_subtable_header because of the different
> layout and field sizes.
> >
> > Just out of curiosity, why don't we use ACPICA code to parse static
> > ACPI tables in Linux?
> >
> > We have a disassembler for static tables that parses all supported
> > tables. This seems like a duplication of code/effort...
> 
Hi Dan,

> Oh, I thought acpi_table_parse_entries() was the common code.
> What's the ACPICA duplicate?

I was thinking AcpiDmDumpTable(). After looking at this ACPICA code,
I realized that the this ACPICA doesn't actually build a parse tree or data structure.
It loops over the data structure to format the input ACPI table to a file.

To me, it seems like a good idea for Linux and ACPICA to share the same code when
parsing and analyzing these structures. I know that Linux may emit warnings
that are specific to Linux but there are structural analyses that should be the same (such as
checking lengths of tables and subtables so that we don't have out of bounds access).

Erik
Rafael J. Wysocki Dec. 20, 2018, 8:57 a.m. UTC | #7
On Thu, Dec 20, 2018 at 2:15 AM Schmauss, Erik <erik.schmauss@intel.com> wrote:
>
>
>
> > -----Original Message-----
> > From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-
> > owner@vger.kernel.org] On Behalf Of Dan Williams
> > Sent: Wednesday, December 19, 2018 4:00 PM
> > To: Schmauss, Erik <erik.schmauss@intel.com>
> > Cc: Rafael J. Wysocki <rafael@kernel.org>; Busch, Keith
> > <keith.busch@intel.com>; Moore, Robert <robert.moore@intel.com>;
> > Linux Kernel Mailing List <linux-kernel@vger.kernel.org>; ACPI Devel
> > Maling List <linux-acpi@vger.kernel.org>; Linux Memory Management
> > List <linux-mm@kvack.org>; Greg Kroah-Hartman
> > <gregkh@linuxfoundation.org>; Hansen, Dave
> > <dave.hansen@intel.com>
> > Subject: Re: [PATCHv2 01/12] acpi: Create subtable parsing
> > infrastructure
> >
> > On Wed, Dec 19, 2018 at 3:19 PM Schmauss, Erik
> > <erik.schmauss@intel.com> wrote:
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-
> > > > owner@vger.kernel.org] On Behalf Of Rafael J. Wysocki
> > > > Sent: Tuesday, December 11, 2018 1:45 AM
> > > > To: Busch, Keith <keith.busch@intel.com>
> > > > Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>; ACPI
> > > > Devel Maling List <linux-acpi@vger.kernel.org>; Linux Memory
> > > > Management List <linux-mm@kvack.org>; Greg Kroah-Hartman
> > > > <gregkh@linuxfoundation.org>; Rafael J. Wysocki
> > <rafael@kernel.org>;
> > > > Hansen, Dave <dave.hansen@intel.com>; Williams, Dan J
> > > > <dan.j.williams@intel.com>
> > > > Subject: Re: [PATCHv2 01/12] acpi: Create subtable parsing
> > > > infrastructure
> > > >
> > > > On Tue, Dec 11, 2018 at 2:05 AM Keith Busch
> > <keith.busch@intel.com>
> > > > wrote:
> > > > >
> > >
> > > Hi Rafael and Bob,
> > >
> > > > > Parsing entries in an ACPI table had assumed a generic header
> > > > > structure that is most common. There is no standard ACPI
> > header,
> > > > > though, so less common types would need custom parsers if they
> > > > > want go through their sub-table entry list.
> > > >
> > > > It looks like the problem at hand is that acpi_hmat_structure is
> > > > incompatible with acpi_subtable_header because of the different
> > layout and field sizes.
> > >
> > > Just out of curiosity, why don't we use ACPICA code to parse static
> > > ACPI tables in Linux?
> > >
> > > We have a disassembler for static tables that parses all supported
> > > tables. This seems like a duplication of code/effort...
> >
> Hi Dan,
>
> > Oh, I thought acpi_table_parse_entries() was the common code.
> > What's the ACPICA duplicate?
>
> I was thinking AcpiDmDumpTable(). After looking at this ACPICA code,
> I realized that the this ACPICA doesn't actually build a parse tree or data structure.
> It loops over the data structure to format the input ACPI table to a file.
>
> To me, it seems like a good idea for Linux and ACPICA to share the same code when
> parsing and analyzing these structures. I know that Linux may emit warnings
> that are specific to Linux but there are structural analyses that should be the same (such as
> checking lengths of tables and subtables so that we don't have out of bounds access).

I agree.

I guess the reason why it has not been done this way was because
nobody thought about it. :-)

So a project to consolidate these things might be a good one.
Schmauss, Erik Dec. 20, 2018, 7 p.m. UTC | #8
> -----Original Message-----
> From: Rafael J. Wysocki [mailto:rafael@kernel.org]
> Sent: Thursday, December 20, 2018 12:57 AM
> To: Schmauss, Erik <erik.schmauss@intel.com>
> Cc: Williams, Dan J <dan.j.williams@intel.com>; Rafael J. Wysocki
> <rafael@kernel.org>; Busch, Keith <keith.busch@intel.com>; Moore,
> Robert <robert.moore@intel.com>; Linux Kernel Mailing List <linux-
> kernel@vger.kernel.org>; ACPI Devel Maling List <linux-
> acpi@vger.kernel.org>; Linux Memory Management List <linux-
> mm@kvack.org>; Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>; Hansen, Dave
> <dave.hansen@intel.com>
> Subject: Re: [PATCHv2 01/12] acpi: Create subtable parsing
> infrastructure
> 
> On Thu, Dec 20, 2018 at 2:15 AM Schmauss, Erik
> <erik.schmauss@intel.com> wrote:
> >
> >
> >
> > > -----Original Message-----
> > > From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-
> > > owner@vger.kernel.org] On Behalf Of Dan Williams
> > > Sent: Wednesday, December 19, 2018 4:00 PM
> > > To: Schmauss, Erik <erik.schmauss@intel.com>
> > > Cc: Rafael J. Wysocki <rafael@kernel.org>; Busch, Keith
> > > <keith.busch@intel.com>; Moore, Robert
> <robert.moore@intel.com>;
> > > Linux Kernel Mailing List <linux-kernel@vger.kernel.org>; ACPI
> Devel
> > > Maling List <linux-acpi@vger.kernel.org>; Linux Memory
> Management
> > > List <linux-mm@kvack.org>; Greg Kroah-Hartman
> > > <gregkh@linuxfoundation.org>; Hansen, Dave
> <dave.hansen@intel.com>
> > > Subject: Re: [PATCHv2 01/12] acpi: Create subtable parsing
> > > infrastructure
> > >
> > > On Wed, Dec 19, 2018 at 3:19 PM Schmauss, Erik
> > > <erik.schmauss@intel.com> wrote:
> > > >
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-
> > > > > owner@vger.kernel.org] On Behalf Of Rafael J. Wysocki
> > > > > Sent: Tuesday, December 11, 2018 1:45 AM
> > > > > To: Busch, Keith <keith.busch@intel.com>
> > > > > Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>;
> > > > > ACPI Devel Maling List <linux-acpi@vger.kernel.org>; Linux
> > > > > Memory Management List <linux-mm@kvack.org>; Greg
> Kroah-Hartman
> > > > > <gregkh@linuxfoundation.org>; Rafael J. Wysocki
> > > <rafael@kernel.org>;
> > > > > Hansen, Dave <dave.hansen@intel.com>; Williams, Dan J
> > > > > <dan.j.williams@intel.com>
> > > > > Subject: Re: [PATCHv2 01/12] acpi: Create subtable parsing
> > > > > infrastructure
> > > > >
> > > > > On Tue, Dec 11, 2018 at 2:05 AM Keith Busch
> > > <keith.busch@intel.com>
> > > > > wrote:
> > > > > >
> > > >
> > > > Hi Rafael and Bob,
> > > >
> > > > > > Parsing entries in an ACPI table had assumed a generic header
> > > > > > structure that is most common. There is no standard ACPI
> > > header,
> > > > > > though, so less common types would need custom parsers if
> they
> > > > > > want go through their sub-table entry list.
> > > > >
> > > > > It looks like the problem at hand is that acpi_hmat_structure is
> > > > > incompatible with acpi_subtable_header because of the
> different
> > > layout and field sizes.
> > > >
> > > > Just out of curiosity, why don't we use ACPICA code to parse
> > > > static ACPI tables in Linux?
> > > >
> > > > We have a disassembler for static tables that parses all supported
> > > > tables. This seems like a duplication of code/effort...
> > >
> > Hi Dan,
> >
> > > Oh, I thought acpi_table_parse_entries() was the common code.
> > > What's the ACPICA duplicate?
> >
> > I was thinking AcpiDmDumpTable(). After looking at this ACPICA
> code, I
> > realized that the this ACPICA doesn't actually build a parse tree or
> data structure.
> > It loops over the data structure to format the input ACPI table to a
> file.
> >
> > To me, it seems like a good idea for Linux and ACPICA to share the
> > same code when parsing and analyzing these structures. I know that
> > Linux may emit warnings that are specific to Linux but there are
> > structural analyses that should be the same (such as checking lengths
> of tables and subtables so that we don't have out of bounds access).
> 
> I agree.
> 
> I guess the reason why it has not been done this way was because
> nobody thought about it. :-)
> 
> So a project to consolidate these things might be a good one.

Ok, I'll talk to Bob about it and see what we can do
diff mbox series

Patch

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 06635fbca81c..58561b4df09d 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -197,7 +197,7 @@  static int acpi_register_lapic(int id, u32 acpiid, u8 enabled)
 }
 
 static int __init
-acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
+acpi_parse_x2apic(union acpi_subtable_headers *header, const unsigned long end)
 {
 	struct acpi_madt_local_x2apic *processor = NULL;
 #ifdef CONFIG_X86_X2APIC
@@ -210,7 +210,7 @@  acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
 	if (BAD_MADT_ENTRY(processor, end))
 		return -EINVAL;
 
-	acpi_table_print_madt_entry(header);
+	acpi_table_print_madt_entry(&header->common);
 
 #ifdef CONFIG_X86_X2APIC
 	apic_id = processor->local_apic_id;
@@ -242,7 +242,7 @@  acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
 }
 
 static int __init
-acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end)
+acpi_parse_lapic(union acpi_subtable_headers * header, const unsigned long end)
 {
 	struct acpi_madt_local_apic *processor = NULL;
 
@@ -251,7 +251,7 @@  acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end)
 	if (BAD_MADT_ENTRY(processor, end))
 		return -EINVAL;
 
-	acpi_table_print_madt_entry(header);
+	acpi_table_print_madt_entry(&header->common);
 
 	/* Ignore invalid ID */
 	if (processor->id == 0xff)
@@ -272,7 +272,7 @@  acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end)
 }
 
 static int __init
-acpi_parse_sapic(struct acpi_subtable_header *header, const unsigned long end)
+acpi_parse_sapic(union acpi_subtable_headers *header, const unsigned long end)
 {
 	struct acpi_madt_local_sapic *processor = NULL;
 
@@ -281,7 +281,7 @@  acpi_parse_sapic(struct acpi_subtable_header *header, const unsigned long end)
 	if (BAD_MADT_ENTRY(processor, end))
 		return -EINVAL;
 
-	acpi_table_print_madt_entry(header);
+	acpi_table_print_madt_entry(&header->common);
 
 	acpi_register_lapic((processor->id << 8) | processor->eid,/* APIC ID */
 			    processor->processor_id, /* ACPI ID */
@@ -291,7 +291,7 @@  acpi_parse_sapic(struct acpi_subtable_header *header, const unsigned long end)
 }
 
 static int __init
-acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,
+acpi_parse_lapic_addr_ovr(union acpi_subtable_headers * header,
 			  const unsigned long end)
 {
 	struct acpi_madt_local_apic_override *lapic_addr_ovr = NULL;
@@ -301,7 +301,7 @@  acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,
 	if (BAD_MADT_ENTRY(lapic_addr_ovr, end))
 		return -EINVAL;
 
-	acpi_table_print_madt_entry(header);
+	acpi_table_print_madt_entry(&header->common);
 
 	acpi_lapic_addr = lapic_addr_ovr->address;
 
@@ -309,7 +309,7 @@  acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,
 }
 
 static int __init
-acpi_parse_x2apic_nmi(struct acpi_subtable_header *header,
+acpi_parse_x2apic_nmi(union acpi_subtable_headers *header,
 		      const unsigned long end)
 {
 	struct acpi_madt_local_x2apic_nmi *x2apic_nmi = NULL;
@@ -319,7 +319,7 @@  acpi_parse_x2apic_nmi(struct acpi_subtable_header *header,
 	if (BAD_MADT_ENTRY(x2apic_nmi, end))
 		return -EINVAL;
 
-	acpi_table_print_madt_entry(header);
+	acpi_table_print_madt_entry(&header->common);
 
 	if (x2apic_nmi->lint != 1)
 		printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
@@ -328,7 +328,7 @@  acpi_parse_x2apic_nmi(struct acpi_subtable_header *header,
 }
 
 static int __init
-acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end)
+acpi_parse_lapic_nmi(union acpi_subtable_headers * header, const unsigned long end)
 {
 	struct acpi_madt_local_apic_nmi *lapic_nmi = NULL;
 
@@ -337,7 +337,7 @@  acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e
 	if (BAD_MADT_ENTRY(lapic_nmi, end))
 		return -EINVAL;
 
-	acpi_table_print_madt_entry(header);
+	acpi_table_print_madt_entry(&header->common);
 
 	if (lapic_nmi->lint != 1)
 		printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
@@ -449,7 +449,7 @@  static int __init mp_register_ioapic_irq(u8 bus_irq, u8 polarity,
 }
 
 static int __init
-acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
+acpi_parse_ioapic(union acpi_subtable_headers * header, const unsigned long end)
 {
 	struct acpi_madt_io_apic *ioapic = NULL;
 	struct ioapic_domain_cfg cfg = {
@@ -462,7 +462,7 @@  acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
 	if (BAD_MADT_ENTRY(ioapic, end))
 		return -EINVAL;
 
-	acpi_table_print_madt_entry(header);
+	acpi_table_print_madt_entry(&header->common);
 
 	/* Statically assign IRQ numbers for IOAPICs hosting legacy IRQs */
 	if (ioapic->global_irq_base < nr_legacy_irqs())
@@ -508,7 +508,7 @@  static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
 }
 
 static int __init
-acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
+acpi_parse_int_src_ovr(union acpi_subtable_headers * header,
 		       const unsigned long end)
 {
 	struct acpi_madt_interrupt_override *intsrc = NULL;
@@ -518,7 +518,7 @@  acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
 	if (BAD_MADT_ENTRY(intsrc, end))
 		return -EINVAL;
 
-	acpi_table_print_madt_entry(header);
+	acpi_table_print_madt_entry(&header->common);
 
 	if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
 		acpi_sci_ioapic_setup(intsrc->source_irq,
@@ -550,7 +550,7 @@  acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
 }
 
 static int __init
-acpi_parse_nmi_src(struct acpi_subtable_header * header, const unsigned long end)
+acpi_parse_nmi_src(union acpi_subtable_headers * header, const unsigned long end)
 {
 	struct acpi_madt_nmi_source *nmi_src = NULL;
 
@@ -559,7 +559,7 @@  acpi_parse_nmi_src(struct acpi_subtable_header * header, const unsigned long end
 	if (BAD_MADT_ENTRY(nmi_src, end))
 		return -EINVAL;
 
-	acpi_table_print_madt_entry(header);
+	acpi_table_print_madt_entry(&header->common);
 
 	/* TBD: Support nimsrc entries? */
 
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 274699463b4f..f5e09c39ff22 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -338,7 +338,7 @@  acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
 }
 
 static int __init
-acpi_parse_x2apic_affinity(struct acpi_subtable_header *header,
+acpi_parse_x2apic_affinity(union acpi_subtable_headers *header,
 			   const unsigned long end)
 {
 	struct acpi_srat_x2apic_cpu_affinity *processor_affinity;
@@ -347,7 +347,7 @@  acpi_parse_x2apic_affinity(struct acpi_subtable_header *header,
 	if (!processor_affinity)
 		return -EINVAL;
 
-	acpi_table_print_srat_entry(header);
+	acpi_table_print_srat_entry(&header->common);
 
 	/* let architecture-dependent part to do it */
 	acpi_numa_x2apic_affinity_init(processor_affinity);
@@ -356,7 +356,7 @@  acpi_parse_x2apic_affinity(struct acpi_subtable_header *header,
 }
 
 static int __init
-acpi_parse_processor_affinity(struct acpi_subtable_header *header,
+acpi_parse_processor_affinity(union acpi_subtable_headers *header,
 			      const unsigned long end)
 {
 	struct acpi_srat_cpu_affinity *processor_affinity;
@@ -365,7 +365,7 @@  acpi_parse_processor_affinity(struct acpi_subtable_header *header,
 	if (!processor_affinity)
 		return -EINVAL;
 
-	acpi_table_print_srat_entry(header);
+	acpi_table_print_srat_entry(&header->common);
 
 	/* let architecture-dependent part to do it */
 	acpi_numa_processor_affinity_init(processor_affinity);
@@ -374,7 +374,7 @@  acpi_parse_processor_affinity(struct acpi_subtable_header *header,
 }
 
 static int __init
-acpi_parse_gicc_affinity(struct acpi_subtable_header *header,
+acpi_parse_gicc_affinity(union acpi_subtable_headers *header,
 			 const unsigned long end)
 {
 	struct acpi_srat_gicc_affinity *processor_affinity;
@@ -383,7 +383,7 @@  acpi_parse_gicc_affinity(struct acpi_subtable_header *header,
 	if (!processor_affinity)
 		return -EINVAL;
 
-	acpi_table_print_srat_entry(header);
+	acpi_table_print_srat_entry(&header->common);
 
 	/* let architecture-dependent part to do it */
 	acpi_numa_gicc_affinity_init(processor_affinity);
@@ -394,7 +394,7 @@  acpi_parse_gicc_affinity(struct acpi_subtable_header *header,
 static int __initdata parsed_numa_memblks;
 
 static int __init
-acpi_parse_memory_affinity(struct acpi_subtable_header * header,
+acpi_parse_memory_affinity(union acpi_subtable_headers * header,
 			   const unsigned long end)
 {
 	struct acpi_srat_mem_affinity *memory_affinity;
@@ -403,7 +403,7 @@  acpi_parse_memory_affinity(struct acpi_subtable_header * header,
 	if (!memory_affinity)
 		return -EINVAL;
 
-	acpi_table_print_srat_entry(header);
+	acpi_table_print_srat_entry(&header->common);
 
 	/* let architecture-dependent part to do it */
 	if (!acpi_numa_memory_affinity_init(memory_affinity))
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index bd1c59fb0e17..d98d5da6a279 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2234,10 +2234,10 @@  static struct acpi_probe_entry *ape;
 static int acpi_probe_count;
 static DEFINE_MUTEX(acpi_probe_mutex);
 
-static int __init acpi_match_madt(struct acpi_subtable_header *header,
+static int __init acpi_match_madt(union acpi_subtable_headers *header,
 				  const unsigned long end)
 {
-	if (!ape->subtable_valid || ape->subtable_valid(header, ape))
+	if (!ape->subtable_valid || ape->subtable_valid(&header->common, ape))
 		if (!ape->probe_subtbl(header, end))
 			acpi_probe_count++;
 
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 61203eebf3a1..e9643b4267c7 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -49,6 +49,15 @@  static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata;
 
 static int acpi_apic_instance __initdata;
 
+enum acpi_subtable_type {
+	ACPI_SUBTABLE_COMMON,
+};
+
+struct acpi_subtable_entry {
+	union acpi_subtable_headers *hdr;
+	enum acpi_subtable_type type;
+};
+
 /*
  * Disable table checksum verification for the early stage due to the size
  * limitation of the current x86 early mapping implementation.
@@ -217,6 +226,42 @@  void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
 	}
 }
 
+static unsigned long __init
+acpi_get_entry_type(struct acpi_subtable_entry *entry)
+{
+	switch (entry->type) {
+	case ACPI_SUBTABLE_COMMON:
+		return entry->hdr->common.type;
+	}
+	return 0;
+}
+
+static unsigned long __init
+acpi_get_entry_length(struct acpi_subtable_entry *entry)
+{
+	switch (entry->type) {
+	case ACPI_SUBTABLE_COMMON:
+		return entry->hdr->common.length;
+	}
+	return 0;
+}
+
+static unsigned long __init
+acpi_get_subtable_header_length(struct acpi_subtable_entry *entry)
+{
+	switch (entry->type) {
+	case ACPI_SUBTABLE_COMMON:
+		return sizeof(entry->hdr->common);
+	}
+	return 0;
+}
+
+static enum acpi_subtable_type __init
+acpi_get_subtable_type(char *id)
+{
+	return ACPI_SUBTABLE_COMMON;
+}
+
 /**
  * acpi_parse_entries_array - for each proc_num find a suitable subtable
  *
@@ -246,8 +291,8 @@  acpi_parse_entries_array(char *id, unsigned long table_size,
 		struct acpi_subtable_proc *proc, int proc_num,
 		unsigned int max_entries)
 {
-	struct acpi_subtable_header *entry;
-	unsigned long table_end;
+	struct acpi_subtable_entry entry;
+	unsigned long table_end, subtable_len, entry_len;
 	int count = 0;
 	int errs = 0;
 	int i;
@@ -270,19 +315,20 @@  acpi_parse_entries_array(char *id, unsigned long table_size,
 
 	/* Parse all entries looking for a match. */
 
-	entry = (struct acpi_subtable_header *)
+	entry.type = acpi_get_subtable_type(id);
+	entry.hdr = (union acpi_subtable_headers *)
 	    ((unsigned long)table_header + table_size);
+	subtable_len = acpi_get_subtable_header_length(&entry);
 
-	while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
-	       table_end) {
+	while (((unsigned long)entry.hdr) + subtable_len  < table_end) {
 		if (max_entries && count >= max_entries)
 			break;
 
 		for (i = 0; i < proc_num; i++) {
-			if (entry->type != proc[i].id)
+			if (acpi_get_entry_type(&entry) != proc[i].id)
 				continue;
 			if (!proc[i].handler ||
-			     (!errs && proc[i].handler(entry, table_end))) {
+			     (!errs && proc[i].handler(entry.hdr, table_end))) {
 				errs++;
 				continue;
 			}
@@ -297,13 +343,14 @@  acpi_parse_entries_array(char *id, unsigned long table_size,
 		 * If entry->length is 0, break from this loop to avoid
 		 * infinite loop.
 		 */
-		if (entry->length == 0) {
+		entry_len = acpi_get_entry_length(&entry);
+		if (entry_len == 0) {
 			pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, proc->id);
 			return -EINVAL;
 		}
 
-		entry = (struct acpi_subtable_header *)
-		    ((unsigned long)entry + entry->length);
+		entry.hdr = (union acpi_subtable_headers *)
+		    ((unsigned long)entry.hdr + entry_len);
 	}
 
 	if (max_entries && count > max_entries) {
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 8f87f40c9460..ef3f72196ad6 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -1383,7 +1383,7 @@  gic_acpi_parse_madt_redist(struct acpi_subtable_header *header,
 }
 
 static int __init
-gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
+gic_acpi_parse_madt_gicc(union acpi_subtable_headers *header,
 			 const unsigned long end)
 {
 	struct acpi_madt_generic_interrupt *gicc =
diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index 256f18b67e8a..08a0a3517138 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -382,7 +382,7 @@  static const struct mbox_chan_ops pcc_chan_ops = {
  *
  * This gets called for each entry in the PCC table.
  */
-static int parse_pcc_subspace(struct acpi_subtable_header *header,
+static int parse_pcc_subspace(union acpi_subtable_headers *header,
 		const unsigned long end)
 {
 	struct acpi_pcct_subspace *ss = (struct acpi_pcct_subspace *) header;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index ed80f147bd50..18805a967c70 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -141,10 +141,13 @@  enum acpi_address_range_id {
 
 
 /* Table Handlers */
+union acpi_subtable_headers {
+	struct acpi_subtable_header common;
+};
 
 typedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table);
 
-typedef int (*acpi_tbl_entry_handler)(struct acpi_subtable_header *header,
+typedef int (*acpi_tbl_entry_handler)(union acpi_subtable_headers *header,
 				      const unsigned long end);
 
 /* Debugger support */