* [PATCH 2/8] SFI: include/linux/sfi.h
2009-06-23 7:13 ` [PATCH 1/8] SFI: Simple Firmware Interface - new Linux sub-system Len Brown
@ 2009-06-23 7:14 ` Len Brown
2009-06-23 7:28 ` Ingo Molnar
2009-06-23 9:06 ` Sam Ravnborg
2009-06-23 7:14 ` [PATCH 3/8] SFI: core support Len Brown
` (6 subsequent siblings)
7 siblings, 2 replies; 53+ messages in thread
From: Len Brown @ 2009-06-23 7:14 UTC (permalink / raw)
To: sfi-devel, linux-kernel; +Cc: Feng Tang, Len Brown
From: Feng Tang <feng.tang@intel.com>
linux/include/sfi.h defines everything that customers
of SFI need to know in order to use the SFI suport in the kernel.
The primary API is sfi_table_parse(), where a driver or another part
of the kernel can supply a handler to parse the named table.
Signed-off-by: Feng Tang <feng.tang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
include/linux/sfi.h | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 161 insertions(+), 0 deletions(-)
create mode 100644 include/linux/sfi.h
diff --git a/include/linux/sfi.h b/include/linux/sfi.h
new file mode 100644
index 0000000..2164fc1
--- /dev/null
+++ b/include/linux/sfi.h
@@ -0,0 +1,161 @@
+/* sfi.h Simple Firmware Interface */
+
+/*
+ * Copyright (C) 2009, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef _LINUX_SFI_H
+#define _LINUX_SFI_H
+
+#ifdef CONFIG_SFI
+
+#define SFI_SYST_SEARCH_BEGIN 0x000E0000
+#define SFI_SYST_SEARCH_END 0x000FFFFF
+
+/* Table signatures reserved by the SFI specification */
+#define SFI_SIG_SYST "SYST"
+#define SFI_SIG_FREQ "FREQ"
+#define SFI_SIG_IDLE "IDLE"
+#define SFI_SIG_CPUS "CPUS"
+#define SFI_SIG_MTMR "MTMR"
+#define SFI_SIG_MRTC "MRTC"
+#define SFI_SIG_MMAP "MMAP"
+#define SFI_SIG_APIC "APIC"
+#define SFI_SIG_XSDT "XSDT" /* ACPI Extended System Description Table */
+#define SFI_SIG_WAKE "WAKE"
+
+#define SFI_SIGNATURE_SIZE 4
+#define SFI_OEM_ID_SIZE 6
+#define SFI_OEM_TABLE_ID_SIZE 8
+
+#define SFI_GET_ENTRY_NUM(ptable, entry) \
+ ((ptable->header.length - sizeof(struct sfi_table_header)) / \
+ (sizeof(struct entry)))
+/*
+ * Table structures must be byte-packed to match the SFI specification,
+ * as they are provided by the BIOS.
+ */
+#pragma pack(1)
+struct sfi_table_header {
+ char signature[SFI_SIGNATURE_SIZE];
+ u32 length;
+ u8 revision;
+ u8 checksum;
+ char oem_id[SFI_OEM_ID_SIZE];
+ char oem_table_id[SFI_OEM_TABLE_ID_SIZE];
+};
+
+struct sfi_table_simple {
+ struct sfi_table_header header;
+ u64 pentry[1];
+};
+
+/* comply with UEFI spec 2.1 */
+struct sfi_mem_entry {
+ u32 type;
+ u64 phy_start;
+ u64 vir_start;
+ u64 pages;
+ u64 attrib;
+};
+
+struct sfi_cpu_table_entry {
+ u32 apicid;
+};
+
+struct sfi_cstate_table_entry {
+ u32 hint; /* MWAIT hint */
+ u32 latency; /* latency in ms */
+};
+
+struct sfi_apic_table_entry {
+ u64 phy_addr; /* phy base addr for APIC reg */
+};
+
+struct sfi_freq_table_entry {
+ u32 freq;
+ u32 latency; /* transition latency in ms */
+ u32 ctrl_val; /* value to write to PERF_CTL to enter this state */
+};
+
+struct sfi_wake_table_entry {
+ u64 phy_addr;
+};
+
+struct sfi_timer_table_entry {
+ u64 phy_addr; /* phy base addr for the timer */
+ u32 freq; /* in HZ */
+ u32 irq;
+};
+
+struct sfi_rtc_table_entry {
+ u64 phy_addr; /* phy base addr for the RTC */
+ u32 irq;
+};
+#pragma pack()
+
+extern int __init sfi_init_memory_map(void);
+extern int __init sfi_init(void);
+extern int __init sfi_platform_init(void);
+extern void __init sfi_init_late(void);
+
+typedef int (*sfi_table_handler) (struct sfi_table_header *table);
+
+int sfi_table_parse(char *signature, char *oem_id, char* oem_table_id,
+ uint flag, sfi_table_handler handler);
+
+void __init __iomem *
+arch_early_ioremap(unsigned long phys, unsigned long size);
+void __init arch_early_iounmap(void __iomem *virt, unsigned long size);
+
+
+extern int sfi_disabled;
+static inline void disable_sfi(void) { sfi_disabled = 1; }
+
+
+#else /* !CONFIG_SFI */
+
+static inline int sfi_init_memory_map(void) { return -1; }
+static inline int sfi_init(void) { return 0; }
+static inline void sfi_init_late(void) {}
+#define sfi_disabled 0
+
+static inline int sfi_table_parse(char *signature, char *oem_id, char* oem_table_id,
+ unsigned int flags, sfi_table_handler handler) { return -1; }
+
+#endif /* CONFIG_SFI */
+
+#endif /*_LINUX_SFI_H*/
--
1.6.0.6
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH 2/8] SFI: include/linux/sfi.h
2009-06-23 7:14 ` [PATCH 2/8] SFI: include/linux/sfi.h Len Brown
@ 2009-06-23 7:28 ` Ingo Molnar
2009-06-23 7:47 ` Feng Tang
2009-06-30 21:57 ` Andrew Morton
2009-06-23 9:06 ` Sam Ravnborg
1 sibling, 2 replies; 53+ messages in thread
From: Ingo Molnar @ 2009-06-23 7:28 UTC (permalink / raw)
To: Len Brown; +Cc: sfi-devel, linux-kernel, Feng Tang, Len Brown
* Len Brown <lenb@kernel.org> wrote:
> +/*
> + * Table structures must be byte-packed to match the SFI specification,
> + * as they are provided by the BIOS.
> + */
> +#pragma pack(1)
We use __attribute__((packed)) for that generally.
> +struct sfi_table_header {
> + char signature[SFI_SIGNATURE_SIZE];
> + u32 length;
> + u8 revision;
> + u8 checksum;
> + char oem_id[SFI_OEM_ID_SIZE];
> + char oem_table_id[SFI_OEM_TABLE_ID_SIZE];
> +};
Please use more readable structure definitions, such as:
> +struct sfi_table_header {
> + char signature[SFI_SIGNATURE_SIZE];
> + u32 length;
> + u8 revision;
> + u8 checksum;
> + char oem_id[SFI_OEM_ID_SIZE];
> + char oem_table_id[SFI_OEM_TABLE_ID_SIZE];
> +};
> +void __init __iomem *
> +arch_early_ioremap(unsigned long phys, unsigned long size);
> +void __init arch_early_iounmap(void __iomem *virt, unsigned long size);
Why is this in sfr.h? Should be in a separate series.
> +static inline int sfi_init_memory_map(void) { return -1; }
> +static inline int sfi_init(void) { return 0; }
> +static inline void sfi_init_late(void) {}
Seems half-aligned. Please align consistently, such as:
static inline int sfi_init_memory_map(void) { return -1; }
static inline int sfi_init(void) { return 0; }
static inline void sfi_init_late(void) { }
or dont align at all.
Ingo
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH 2/8] SFI: include/linux/sfi.h
2009-06-23 7:28 ` Ingo Molnar
@ 2009-06-23 7:47 ` Feng Tang
2009-06-23 8:00 ` Ingo Molnar
2009-06-30 21:57 ` Andrew Morton
1 sibling, 1 reply; 53+ messages in thread
From: Feng Tang @ 2009-06-23 7:47 UTC (permalink / raw)
To: Ingo Molnar
Cc: Len Brown, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org, Brown, Len
On Tue, 23 Jun 2009 15:28:11 +0800
Ingo Molnar <mingo@elte.hu> wrote:
>
> * Len Brown <lenb@kernel.org> wrote:
>
> > +/*
> > + * Table structures must be byte-packed to match the SFI
> > specification,
> > + * as they are provided by the BIOS.
> > + */
> > +#pragma pack(1)
>
> We use __attribute__((packed)) for that generally.
>
> > +struct sfi_table_header {
> > + char signature[SFI_SIGNATURE_SIZE];
> > + u32 length;
> > + u8 revision;
> > + u8 checksum;
> > + char oem_id[SFI_OEM_ID_SIZE];
> > + char oem_table_id[SFI_OEM_TABLE_ID_SIZE];
> > +};
>
> Please use more readable structure definitions, such as:
>
> > +struct sfi_table_header {
> > + char signature[SFI_SIGNATURE_SIZE];
> > + u32 length;
> > + u8 revision;
> > + u8 checksum;
> > + char oem_id[SFI_OEM_ID_SIZE];
> > + char
> > oem_table_id[SFI_OEM_TABLE_ID_SIZE]; +};
>
> > +void __init __iomem *
> > +arch_early_ioremap(unsigned long phys, unsigned long size);
> > +void __init arch_early_iounmap(void __iomem *virt, unsigned long
> > size);
>
> Why is this in sfr.h? Should be in a separate series.
Thanks for your great comments, will address them.
For these arch_early_ioremap/arch_early_iounmap API, do you mean we should
put it in a sfi.h under "asm" folder? The reason we put it here is to
give a arch independent API declaration here and let each arch implement
its own func.
Thanks,
Feng
>
> > +static inline int sfi_init_memory_map(void) { return -1; }
> > +static inline int sfi_init(void) { return 0; }
> > +static inline void sfi_init_late(void) {}
>
> Seems half-aligned. Please align consistently, such as:
>
> static inline int sfi_init_memory_map(void) { return -1; }
> static inline int sfi_init(void) { return 0; }
> static inline void sfi_init_late(void) { }
>
> or dont align at all.
>
> Ingo
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH 2/8] SFI: include/linux/sfi.h
2009-06-23 7:47 ` Feng Tang
@ 2009-06-23 8:00 ` Ingo Molnar
2009-06-23 8:02 ` Feng Tang
0 siblings, 1 reply; 53+ messages in thread
From: Ingo Molnar @ 2009-06-23 8:00 UTC (permalink / raw)
To: Feng Tang
Cc: Len Brown, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org, Brown, Len, Thomas Gleixner,
H. Peter Anvin, Yinghai Lu
* Feng Tang <feng.tang@intel.com> wrote:
> For these arch_early_ioremap/arch_early_iounmap API, do you mean
> we should put it in a sfi.h under "asm" folder? The reason we put
> it here is to give a arch independent API declaration here and let
> each arch implement its own func.
Yeah, i'd suggest to create a new early-remap.h and early-remap.c
kind of file to collect the existing bits for that. It's a bit ugly
(not really the fault of SFI - these are pre-existing facilities)
and might need some love - we better move it apart so that the light
of attention shines on it.
What's the target merge of the SFI stuff, 2.6.31?
Ingo
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH 2/8] SFI: include/linux/sfi.h
2009-06-23 8:00 ` Ingo Molnar
@ 2009-06-23 8:02 ` Feng Tang
2009-06-23 8:09 ` Ingo Molnar
0 siblings, 1 reply; 53+ messages in thread
From: Feng Tang @ 2009-06-23 8:02 UTC (permalink / raw)
To: Ingo Molnar
Cc: Len Brown, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org, Brown, Len, Thomas Gleixner,
H. Peter Anvin, Yinghai Lu
On Tue, 23 Jun 2009 16:00:47 +0800
Ingo Molnar <mingo@elte.hu> wrote:
>
> * Feng Tang <feng.tang@intel.com> wrote:
>
> > For these arch_early_ioremap/arch_early_iounmap API, do you mean
> > we should put it in a sfi.h under "asm" folder? The reason we put
> > it here is to give a arch independent API declaration here and let
> > each arch implement its own func.
>
> Yeah, i'd suggest to create a new early-remap.h and early-remap.c
> kind of file to collect the existing bits for that. It's a bit ugly
> (not really the fault of SFI - these are pre-existing facilities)
> and might need some love - we better move it apart so that the light
> of attention shines on it.
>
> What's the target merge of the SFI stuff, 2.6.31?
AFAIK, Len's target is for 2.6.32
Thanks,
Feng
>
> Ingo
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH 2/8] SFI: include/linux/sfi.h
2009-06-23 8:02 ` Feng Tang
@ 2009-06-23 8:09 ` Ingo Molnar
2009-06-23 15:14 ` H. Peter Anvin
0 siblings, 1 reply; 53+ messages in thread
From: Ingo Molnar @ 2009-06-23 8:09 UTC (permalink / raw)
To: Feng Tang
Cc: Len Brown, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org, Brown, Len, Thomas Gleixner,
H. Peter Anvin, Yinghai Lu
* Feng Tang <feng.tang@intel.com> wrote:
> On Tue, 23 Jun 2009 16:00:47 +0800
> Ingo Molnar <mingo@elte.hu> wrote:
>
> >
> > * Feng Tang <feng.tang@intel.com> wrote:
> >
> > > For these arch_early_ioremap/arch_early_iounmap API, do you mean
> > > we should put it in a sfi.h under "asm" folder? The reason we put
> > > it here is to give a arch independent API declaration here and let
> > > each arch implement its own func.
> >
> > Yeah, i'd suggest to create a new early-remap.h and
> > early-remap.c kind of file to collect the existing bits for
> > that. It's a bit ugly (not really the fault of SFI - these are
> > pre-existing facilities) and might need some love - we better
> > move it apart so that the light of attention shines on it.
> >
> > What's the target merge of the SFI stuff, 2.6.31?
>
> AFAIK, Len's target is for 2.6.32
Ah, ok - then there's time. The code is almost good for .31 btw ;-)
Ingo
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH 2/8] SFI: include/linux/sfi.h
2009-06-23 8:09 ` Ingo Molnar
@ 2009-06-23 15:14 ` H. Peter Anvin
0 siblings, 0 replies; 53+ messages in thread
From: H. Peter Anvin @ 2009-06-23 15:14 UTC (permalink / raw)
To: Ingo Molnar
Cc: Feng Tang, Len Brown, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org, Brown, Len, Thomas Gleixner,
Yinghai Lu
Ingo Molnar wrote:
> * Feng Tang <feng.tang@intel.com> wrote:
>
>> On Tue, 23 Jun 2009 16:00:47 +0800
>> Ingo Molnar <mingo@elte.hu> wrote:
>>
>>> * Feng Tang <feng.tang@intel.com> wrote:
>>>
>>>> For these arch_early_ioremap/arch_early_iounmap API, do you mean
>>>> we should put it in a sfi.h under "asm" folder? The reason we put
>>>> it here is to give a arch independent API declaration here and let
>>>> each arch implement its own func.
>>> Yeah, i'd suggest to create a new early-remap.h and
>>> early-remap.c kind of file to collect the existing bits for
>>> that. It's a bit ugly (not really the fault of SFI - these are
>>> pre-existing facilities) and might need some love - we better
>>> move it apart so that the light of attention shines on it.
>>>
>>> What's the target merge of the SFI stuff, 2.6.31?
>> AFAIK, Len's target is for 2.6.32
>
> Ah, ok - then there's time. The code is almost good for .31 btw ;-)
>
The code is really quite clean; I recommended to Len that he target
2.6.32 not because of the quality of the code, but just to get it plenty
of time to get properly reviewed and any architectural issues getting
fixed properly.
-hpa
--
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel. I don't speak on their behalf.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH 2/8] SFI: include/linux/sfi.h
2009-06-23 7:28 ` Ingo Molnar
2009-06-23 7:47 ` Feng Tang
@ 2009-06-30 21:57 ` Andrew Morton
2009-06-30 21:59 ` Ingo Molnar
1 sibling, 1 reply; 53+ messages in thread
From: Andrew Morton @ 2009-06-30 21:57 UTC (permalink / raw)
To: Ingo Molnar; +Cc: lenb, sfi-devel, linux-kernel, feng.tang, len.brown
On Tue, 23 Jun 2009 09:28:11 +0200
Ingo Molnar <mingo@elte.hu> wrote:
> > +/*
> > + * Table structures must be byte-packed to match the SFI specification,
> > + * as they are provided by the BIOS.
> > + */
> > +#pragma pack(1)
>
> We use __attribute__((packed)) for that generally.
Or __packed. I usually recommend __packed because I can never remember
the weird arrangement of underscores and parentheses in the gcc thing.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH 2/8] SFI: include/linux/sfi.h
2009-06-30 21:57 ` Andrew Morton
@ 2009-06-30 21:59 ` Ingo Molnar
0 siblings, 0 replies; 53+ messages in thread
From: Ingo Molnar @ 2009-06-30 21:59 UTC (permalink / raw)
To: Andrew Morton; +Cc: lenb, sfi-devel, linux-kernel, feng.tang, len.brown
* Andrew Morton <akpm@linux-foundation.org> wrote:
> On Tue, 23 Jun 2009 09:28:11 +0200
> Ingo Molnar <mingo@elte.hu> wrote:
>
> > > +/*
> > > + * Table structures must be byte-packed to match the SFI specification,
> > > + * as they are provided by the BIOS.
> > > + */
> > > +#pragma pack(1)
> >
> > We use __attribute__((packed)) for that generally.
>
> Or __packed. I usually recommend __packed because I can never
> remember the weird arrangement of underscores and parentheses in
> the gcc thing.
Agreed - it's also shorter and more in line with stuff like
__read_mostly, etc.
Ingo
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH 2/8] SFI: include/linux/sfi.h
2009-06-23 7:14 ` [PATCH 2/8] SFI: include/linux/sfi.h Len Brown
2009-06-23 7:28 ` Ingo Molnar
@ 2009-06-23 9:06 ` Sam Ravnborg
2009-06-23 15:52 ` Feng Tang
1 sibling, 1 reply; 53+ messages in thread
From: Sam Ravnborg @ 2009-06-23 9:06 UTC (permalink / raw)
To: Len Brown; +Cc: sfi-devel, linux-kernel, Feng Tang, Len Brown
> +/*
> + * Table structures must be byte-packed to match the SFI specification,
> + * as they are provided by the BIOS.
> + */
> +#pragma pack(1)
> +struct sfi_table_header {
> + char signature[SFI_SIGNATURE_SIZE];
> + u32 length;
> + u8 revision;
> + u8 checksum;
> + char oem_id[SFI_OEM_ID_SIZE];
> + char oem_table_id[SFI_OEM_TABLE_ID_SIZE];
> +};
Are they endian specific?
In that case use the correct endian specific types.
Same for the other types later in this file.
Sam
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH 2/8] SFI: include/linux/sfi.h
2009-06-23 9:06 ` Sam Ravnborg
@ 2009-06-23 15:52 ` Feng Tang
2009-06-23 19:26 ` Sam Ravnborg
0 siblings, 1 reply; 53+ messages in thread
From: Feng Tang @ 2009-06-23 15:52 UTC (permalink / raw)
To: Sam Ravnborg
Cc: Len Brown, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org
On Tue, 23 Jun 2009 17:06:54 +0800
Sam Ravnborg <sam@ravnborg.org> wrote:
> > +/*
> > + * Table structures must be byte-packed to match the SFI
> > specification,
> > + * as they are provided by the BIOS.
> > + */
> > +#pragma pack(1)
> > +struct sfi_table_header {
> > + char signature[SFI_SIGNATURE_SIZE];
> > + u32 length;
> > + u8 revision;
> > + u8 checksum;
> > + char oem_id[SFI_OEM_ID_SIZE];
> > + char oem_table_id[SFI_OEM_TABLE_ID_SIZE];
> > +};
> Are they endian specific?
> In that case use the correct endian specific types.
I can try to answer this question, Len, correct me if I'm wrong.
These SFI tables are just byte strings, and created by FW, FW can chose
to use big-endian or little-endian in these tables based on what platform
they are used. So it's transparent for SFI driver code.
Thanks,
Feng
>
> Same for the other types later in this file.
>
> Sam
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH 2/8] SFI: include/linux/sfi.h
2009-06-23 15:52 ` Feng Tang
@ 2009-06-23 19:26 ` Sam Ravnborg
0 siblings, 0 replies; 53+ messages in thread
From: Sam Ravnborg @ 2009-06-23 19:26 UTC (permalink / raw)
To: Feng Tang
Cc: Len Brown, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org
On Tue, Jun 23, 2009 at 11:52:17PM +0800, Feng Tang wrote:
> On Tue, 23 Jun 2009 17:06:54 +0800
> Sam Ravnborg <sam@ravnborg.org> wrote:
>
> > > +/*
> > > + * Table structures must be byte-packed to match the SFI
> > > specification,
> > > + * as they are provided by the BIOS.
> > > + */
> > > +#pragma pack(1)
> > > +struct sfi_table_header {
> > > + char signature[SFI_SIGNATURE_SIZE];
> > > + u32 length;
> > > + u8 revision;
> > > + u8 checksum;
> > > + char oem_id[SFI_OEM_ID_SIZE];
> > > + char oem_table_id[SFI_OEM_TABLE_ID_SIZE];
> > > +};
> > Are they endian specific?
> > In that case use the correct endian specific types.
>
> I can try to answer this question, Len, correct me if I'm wrong.
>
> These SFI tables are just byte strings, and created by FW, FW can chose
> to use big-endian or little-endian in these tables based on what platform
> they are used. So it's transparent for SFI driver code.
But we have "u32 length;" - but I guess the signature
tell the endian then.
Sam
^ permalink raw reply [flat|nested] 53+ messages in thread
* [PATCH 3/8] SFI: core support
2009-06-23 7:13 ` [PATCH 1/8] SFI: Simple Firmware Interface - new Linux sub-system Len Brown
2009-06-23 7:14 ` [PATCH 2/8] SFI: include/linux/sfi.h Len Brown
@ 2009-06-23 7:14 ` Len Brown
2009-06-23 7:56 ` Ingo Molnar
2009-06-23 12:32 ` Andi Kleen
2009-06-23 7:14 ` [PATCH 4/8] SFI: Hook boot-time initialization Len Brown
` (5 subsequent siblings)
7 siblings, 2 replies; 53+ messages in thread
From: Len Brown @ 2009-06-23 7:14 UTC (permalink / raw)
To: sfi-devel, linux-kernel; +Cc: Feng Tang, Len Brown
From: Feng Tang <feng.tang@intel.com>
drivers/sfi/sfi_core.c contains the generic SFI implementation.
It has a private header, sfi_core.h, for its own use and the
private use of future files in drivers/sfi/
arch/x86/kernel/sfi.c serves the dual-purpose of supporting the
SFI core with arch specific code, as well as a home for the
arch-specific code that uses SFI.
Signed-off-by: Feng Tang <feng.tang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/x86/kernel/Makefile | 1 +
arch/x86/kernel/sfi.c | 335 ++++++++++++++++++++++++++++++++++++++
drivers/Makefile | 1 +
drivers/sfi/Makefile | 1 +
drivers/sfi/sfi_core.c | 403 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/sfi/sfi_core.h | 63 +++++++
6 files changed, 804 insertions(+), 0 deletions(-)
create mode 100644 arch/x86/kernel/sfi.c
create mode 100644 drivers/sfi/Makefile
create mode 100644 drivers/sfi/sfi_core.c
create mode 100644 drivers/sfi/sfi_core.h
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 88d1bfc..75042a7 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -50,6 +50,7 @@ obj-y += step.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-y += cpu/
obj-y += acpi/
+obj-$(CONFIG_SFI) += sfi.o
obj-y += reboot.o
obj-$(CONFIG_MCA) += mca_32.o
obj-$(CONFIG_X86_MSR) += msr.o
diff --git a/arch/x86/kernel/sfi.c b/arch/x86/kernel/sfi.c
new file mode 100644
index 0000000..d940de2
--- /dev/null
+++ b/arch/x86/kernel/sfi.c
@@ -0,0 +1,335 @@
+/*
+ * sfi.c - SFI Boot Support (refer acpi/boot.c)
+ *
+ * Copyright (C) 2008-2009 Intel Corporation
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+#include <linux/init.h>
+#include <linux/efi.h>
+#include <linux/cpumask.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/io.h>
+#include <linux/acpi.h>
+#include <linux/efi.h>
+#include <linux/sfi.h>
+
+#include <asm/pgtable.h>
+#include <asm/io_apic.h>
+#include <asm/apic.h>
+#include <asm/mpspec.h>
+
+#include <asm/e820.h>
+#include <asm/setup.h>
+
+#undef PREFIX
+#define PREFIX "SFI: "
+
+#ifdef CONFIG_X86_LOCAL_APIC
+static u64 sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
+#endif
+
+extern int __init sfi_parse_xsdt(struct sfi_table_header *table);
+static int __init sfi_parse_cpus(struct sfi_table_header *table);
+static int __init sfi_parse_apic(struct sfi_table_header *table);
+
+void __init __iomem *
+arch_early_ioremap(unsigned long phys, unsigned long size)
+{
+ return early_ioremap(phys, size);
+}
+
+void __init arch_early_iounmap(void __iomem *virt, unsigned long size)
+{
+ early_iounmap(virt, size);
+}
+
+static ulong __init sfi_early_find_syst(void)
+{
+ unsigned long i;
+ char *pchar = (char *)SFI_SYST_SEARCH_BEGIN;
+
+ for (i = 0; SFI_SYST_SEARCH_BEGIN + i < SFI_SYST_SEARCH_END; i += 16, pchar += 16) {
+ if (!strncmp(SFI_SIG_SYST, pchar, SFI_SIGNATURE_SIZE))
+ return SFI_SYST_SEARCH_BEGIN + i;
+ }
+ return 0;
+}
+
+/*
+ * called in a early boot phase before the paging table is created,
+ * setup a mmap table in e820 format
+ */
+int __init sfi_init_memory_map(void)
+{
+ struct sfi_table_simple *syst, *mmapt;
+ struct sfi_mem_entry *mentry;
+ unsigned long long start, end, size;
+ int i, num, type, tbl_cnt;
+ u64 *pentry;
+
+ if (sfi_disabled)
+ return -1;
+
+ /* first search the syst table */
+ syst = (struct sfi_table_simple *)sfi_early_find_syst();
+ if (!syst)
+ return -1;
+
+ tbl_cnt = (syst->header.length - sizeof(struct sfi_table_header)) / sizeof(u64);
+ pentry = syst->pentry;
+
+ /* walk through the syst to search the mmap table */
+ mmapt = NULL;
+ for (i = 0; i < tbl_cnt; i++) {
+ if (!strncmp(SFI_SIG_MMAP, (char *)(u32)*pentry, 4)) {
+ mmapt = (struct sfi_table_simple *)(u32)*pentry;
+ break;
+ }
+ pentry++;
+ }
+ if (!mmapt)
+ return -1;
+
+ /* refer copy_e820_memory() */
+ num = SFI_GET_ENTRY_NUM(mmapt, sfi_mem_entry);
+ mentry = (struct sfi_mem_entry *)mmapt->pentry;
+ for (i = 0; i < num; i++) {
+ start = mentry->phy_start;
+ size = mentry->pages << PAGE_SHIFT;
+ end = start + size;
+
+ if (start > end)
+ return -1;
+
+ pr_debug(PREFIX "start = 0x%08x end = 0x%08x type = %d\n",
+ (u32)start, (u32)end, mentry->type);
+
+ /* translate SFI mmap type to E820 map type */
+ switch (mentry->type) {
+ case EFI_CONVENTIONAL_MEMORY:
+ type = E820_RAM;
+ break;
+ case EFI_MEMORY_MAPPED_IO:
+ case EFI_UNUSABLE_MEMORY:
+ case EFI_RUNTIME_SERVICES_DATA:
+ mentry++;
+ continue;
+ default:
+ type = E820_RESERVED;
+ }
+
+ e820_add_region(start, size, type);
+ mentry++;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_X86_LOCAL_APIC
+void __init mp_sfi_register_lapic_address(u64 address)
+{
+ mp_lapic_addr = (unsigned long) address;
+
+ set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
+
+ if (boot_cpu_physical_apicid == -1U)
+ boot_cpu_physical_apicid = read_apic_id();
+
+ pr_info(PREFIX "Boot CPU = %d\n", boot_cpu_physical_apicid);
+}
+
+/* All CPUs enumerated by SFI must be present and enabled */
+void __cpuinit mp_sfi_register_lapic(u8 id)
+{
+ struct mpc_cpu cpu;
+ int boot_cpu = 0;
+
+ if (MAX_APICS - id <= 0) {
+ printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
+ id, MAX_APICS);
+ return;
+ }
+
+ if (id == boot_cpu_physical_apicid)
+ boot_cpu = 1;
+
+ cpu.type = MP_PROCESSOR;
+ cpu.apicid = id;
+ cpu.apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
+ cpu.cpuflag = CPU_ENABLED;
+ cpu.cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
+ cpu.cpufeature = (boot_cpu_data.x86 << 8) |
+ (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
+ cpu.featureflag = boot_cpu_data.x86_capability[0];
+ cpu.reserved[0] = 0;
+ cpu.reserved[1] = 0;
+
+ generic_processor_info(id, cpu.apicver);
+}
+
+static int __init sfi_parse_cpus(struct sfi_table_header *table)
+{
+ struct sfi_table_simple *sb;
+ struct sfi_cpu_table_entry *pentry;
+ int i;
+ int cpu_num;
+
+ BUG_ON(!table);
+ sb = (struct sfi_table_simple *)table;
+
+ cpu_num = SFI_GET_ENTRY_NUM(sb, sfi_cpu_table_entry);
+ pentry = (struct sfi_cpu_table_entry *) sb->pentry;
+
+ for (i = 0; i < cpu_num; i++) {
+ mp_sfi_register_lapic(pentry->apicid);
+ pentry++;
+ }
+
+ smp_found_config = 1;
+ return 0;
+}
+#endif /* CONFIG_X86_LOCAL_APIC */
+
+#ifdef CONFIG_X86_IO_APIC
+static struct mp_ioapic_routing {
+ int apic_id;
+ int gsi_base;
+ int gsi_end;
+ u32 pin_programmed[4];
+} mp_ioapic_routing[MAX_IO_APICS];
+
+/* refer acpi/boot.c */
+static u8 __init uniq_ioapic_id(u8 id)
+{
+#ifdef CONFIG_X86_32
+ if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
+ !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+ return io_apic_get_unique_id(nr_ioapics, id);
+ else
+ return id;
+#else
+ int i;
+ DECLARE_BITMAP(used, 256);
+ bitmap_zero(used, 256);
+ for (i = 0; i < nr_ioapics; i++) {
+ struct mpc_ioapic *ia = &mp_ioapics[i];
+ __set_bit(ia->apicid, used);
+ }
+ if (!test_bit(id, used))
+ return id;
+ return find_first_zero_bit(used, 256);
+#endif
+}
+
+
+void __init mp_sfi_register_ioapic(u8 id, u32 paddr)
+{
+ int idx = 0;
+ int tmpid;
+ static u32 gsi_base;
+
+ if (nr_ioapics >= MAX_IO_APICS) {
+ printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
+ "(found %d)\n", MAX_IO_APICS, nr_ioapics);
+ panic("Recompile kernel with bigger MAX_IO_APICS!\n");
+ }
+ if (!paddr) {
+ printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
+ " found in MADT table, skipping!\n");
+ return;
+ }
+
+ idx = nr_ioapics;
+
+ mp_ioapics[idx].type = MP_IOAPIC;
+ mp_ioapics[idx].flags = MPC_APIC_USABLE;
+ mp_ioapics[idx].apicaddr = paddr;
+
+ set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, paddr);
+ tmpid = uniq_ioapic_id(id);
+ if (tmpid == -1)
+ return;
+
+ mp_ioapics[idx].apicid = tmpid;
+#ifdef CONFIG_X86_32
+ mp_ioapics[idx].apicver = io_apic_get_version(idx);
+#else
+ mp_ioapics[idx].apicver = 0;
+#endif
+
+ pr_info(PREFIX "IOAPIC[%d]: apic_id %d, version %d, address 0x%x\n",
+ idx, mp_ioapics[idx].apicid,
+ mp_ioapics[idx].apicver, (u32)mp_ioapics[idx].apicaddr);
+ /*
+ * Build basic GSI lookup table to facilitate gsi->io_apic lookups
+ * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
+ */
+ mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].apicid;
+ mp_ioapic_routing[idx].gsi_base = gsi_base;
+ mp_ioapic_routing[idx].gsi_end = gsi_base +
+ io_apic_get_redir_entries(idx);
+ gsi_base = mp_ioapic_routing[idx].gsi_end + 1;
+ pr_info(PREFIX "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
+ "GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
+ mp_ioapics[idx].apicver, (u32)mp_ioapics[idx].apicaddr,
+ mp_ioapic_routing[idx].gsi_base,
+ mp_ioapic_routing[idx].gsi_end);
+
+ nr_ioapics++;
+}
+
+static int __init sfi_parse_apic(struct sfi_table_header *table)
+{
+ struct sfi_table_simple *sb;
+ struct sfi_apic_table_entry *pentry;
+ int i, num;
+
+ BUG_ON(!table);
+ sb = (struct sfi_table_simple *)table;
+
+ num = SFI_GET_ENTRY_NUM(sb, sfi_apic_table_entry);
+ pentry = (struct sfi_apic_table_entry *) sb->pentry;
+ for (i = 0; i < num; i++) {
+ mp_sfi_register_ioapic(i, pentry->phy_addr);
+ pentry++;
+ }
+
+ WARN_ON(pic_mode);
+ pic_mode = 0;
+ return 0;
+}
+#endif /* CONFIG_X86_IO_APIC */
+
+/*
+ * sfi_platform_init(): register lapics & io-apics
+ */
+int __init sfi_platform_init(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+ mp_sfi_register_lapic_address(sfi_lapic_addr);
+ sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, 0, sfi_parse_cpus);
+#endif
+#ifdef CONFIG_X86_IO_APIC
+ sfi_table_parse(SFI_SIG_APIC, NULL, NULL, 0, sfi_parse_apic);
+#endif
+ return 0;
+}
diff --git a/drivers/Makefile b/drivers/Makefile
index 1266ead..c3e39b5 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_PARISC) += parisc/
obj-$(CONFIG_RAPIDIO) += rapidio/
obj-y += video/
obj-$(CONFIG_ACPI) += acpi/
+obj-$(CONFIG_SFI) += sfi/
# PnP must come after ACPI since it will eventually need to check if acpi
# was used and do nothing if so
obj-$(CONFIG_PNP) += pnp/
diff --git a/drivers/sfi/Makefile b/drivers/sfi/Makefile
new file mode 100644
index 0000000..f176470
--- /dev/null
+++ b/drivers/sfi/Makefile
@@ -0,0 +1 @@
+obj-y += sfi_core.o
diff --git a/drivers/sfi/sfi_core.c b/drivers/sfi/sfi_core.c
new file mode 100644
index 0000000..0a9b72d
--- /dev/null
+++ b/drivers/sfi/sfi_core.c
@@ -0,0 +1,403 @@
+/* sfi_core.c Simple Firmware Interface - core internals */
+
+/*
+ * Copyright (C) 2009, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/irq.h>
+#include <linux/errno.h>
+#include <linux/sfi.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+#include "sfi_core.h"
+
+#undef PREFIX
+#define PREFIX "SFI: "
+
+int sfi_disabled;
+EXPORT_SYMBOL(sfi_disabled);
+
+#define SFI_MAX_TABLES 64
+struct sfi_internal_syst sfi_tblist;
+static struct sfi_table_desc sfi_initial_tables[SFI_MAX_TABLES] __initdata;
+
+/*
+ * flag for whether using ioremap() to map the sfi tables, if yes
+ * each table only need be mapped once, otherwise each arch's
+ * early_ioremap and early_iounmap should be used each time a
+ * table is visited
+ */
+static u32 sfi_tbl_permanant_mapped;
+
+static void __iomem *sfi_map_memory(u32 phys, u32 size)
+{
+ if (!phys || !size)
+ return NULL;
+
+ if (sfi_tbl_permanant_mapped)
+ return ioremap((unsigned long)phys, size);
+ else
+ return arch_early_ioremap((unsigned long)phys, size);
+}
+
+static void sfi_unmap_memory(void __iomem *virt, u32 size)
+{
+ if (!virt || !size)
+ return;
+
+ if (sfi_tbl_permanant_mapped)
+ iounmap(virt);
+ else
+ arch_early_iounmap(virt, size);
+}
+
+static void sfi_print_table_header(u32 address,
+ struct sfi_table_header *header)
+{
+ pr_info(PREFIX
+ "%4.4s %08lX, %04X (r%d %6.6s %8.8s)\n",
+ header->signature, (unsigned long)address,
+ header->length, header->revision, header->oem_id,
+ header->oem_table_id);
+}
+
+static u8 sfi_checksum_table(u8 *buffer, u32 length)
+{
+ u8 sum = 0;
+
+ while (length--)
+ sum += *buffer++;
+ return sum;
+}
+
+/* Verifies if the table checksums is zero */
+static int sfi_tb_verify_checksum(struct sfi_table_header *table, u32 length)
+{
+ u8 checksum;
+
+ checksum = sfi_checksum_table((u8 *)table, length);
+ if (checksum) {
+ pr_warning(PREFIX
+ "Incorrect checksum in table [%4.4s] - %2.2X,"
+ " should be %2.2X\n", table->signature,
+ table->checksum, (u8)(table->checksum - checksum));
+ return -1;
+ }
+ return 0;
+}
+
+ /* find the right table based on signaure, return the mapped table */
+int sfi_get_table(char *signature, char *oem_id, char *oem_table_id,
+ unsigned int flags, struct sfi_table_header **out_table)
+{
+ struct sfi_table_desc *tdesc;
+ struct sfi_table_header *th;
+ u32 i;
+
+ if (!signature || !out_table)
+ return -1;
+
+ /* Walk the global SFI table list */
+ for (i = 0; i < sfi_tblist.count; i++) {
+ tdesc = &sfi_tblist.tables[i];
+ th = &tdesc->header;
+
+ if ((flags & SFI_ACPI_TABLE) != (tdesc->flags & SFI_ACPI_TABLE))
+ continue;
+
+ if (strncmp(th->signature, signature, SFI_SIGNATURE_SIZE))
+ continue;
+
+ if (oem_id && strncmp(th->oem_id, oem_id, SFI_OEM_ID_SIZE))
+ continue;
+
+ if (oem_table_id && strncmp(th->oem_table_id, oem_table_id,
+ SFI_OEM_TABLE_ID_SIZE))
+ continue;
+
+ if (!tdesc->pointer) {
+ tdesc->pointer = sfi_map_memory(tdesc->address,
+ th->length);
+ if (!tdesc->pointer)
+ return -ENOMEM;
+ }
+ *out_table = tdesc->pointer;
+
+ if (!sfi_tbl_permanant_mapped)
+ tdesc->pointer = NULL;
+
+ return 0;
+ }
+
+ return -1;
+}
+
+void sfi_put_table(struct sfi_table_header *table)
+{
+ if (!sfi_tbl_permanant_mapped)
+ sfi_unmap_memory(table, table->length);
+}
+
+/* find table with signature, run handler on it */
+int sfi_table_parse(char *signature, char *oem_id, char* oem_table_id,
+ unsigned int flags, sfi_table_handler handler)
+{
+ int ret = 0;
+ struct sfi_table_header *table = NULL;
+
+ if (!handler)
+ return -EINVAL;
+
+ sfi_get_table(signature, oem_id, oem_table_id, flags, &table);
+ if (!table)
+ return -1;
+
+ ret = handler(table);
+ sfi_put_table(table);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(sfi_table_parse);
+
+void sfi_tb_install_table(u64 addr, u32 flags)
+{
+ struct sfi_table_header *table;
+ u32 length;
+
+ /* only map table header before knowing actual length */
+ table = sfi_map_memory(addr, sizeof(struct sfi_table_header));
+ if (!table)
+ return;
+
+ length = table->length;
+ sfi_unmap_memory(table, sizeof(struct sfi_table_header));
+
+ table = sfi_map_memory(addr, length);
+ if (!table)
+ return;
+
+ if (sfi_tb_verify_checksum(table, length))
+ goto unmap_and_exit;
+
+ /* Initialize sfi_tblist entry */
+ sfi_tblist.tables[sfi_tblist.count].flags = flags;
+ sfi_tblist.tables[sfi_tblist.count].address = addr;
+ sfi_tblist.tables[sfi_tblist.count].pointer = NULL;
+ memcpy(&sfi_tblist.tables[sfi_tblist.count].header,
+ table, sizeof(struct sfi_table_header));
+
+ sfi_print_table_header(addr, table);
+ sfi_tblist.count++;
+
+unmap_and_exit:
+ sfi_unmap_memory(table, length);
+ return;
+}
+
+/*
+ * Copy system table and associated table headers to internal format
+ */
+static int __init
+sfi_tb_parse_syst(unsigned long syst_addr)
+{
+ struct sfi_table_simple *syst;
+ struct sfi_table_header *table;
+ u64 *paddr;
+ u32 length, tbl_cnt;
+ int status;
+ int i;
+
+ /* 1. map and get the total length of SYST */
+ syst = sfi_map_memory(syst_addr, sizeof(struct sfi_table_simple));
+ if (!syst)
+ return -ENOMEM;
+
+ sfi_print_table_header(syst_addr, (struct sfi_table_header *)syst);
+ table = (struct sfi_table_header *)syst;
+ length = table->length;
+ sfi_unmap_memory(syst, sizeof(struct sfi_table_simple));
+
+ /* 2. remap/verify the SYST and parse the number of entry */
+ syst = sfi_map_memory(syst_addr, length);
+ if (!syst)
+ return -ENOMEM;
+
+ table = (struct sfi_table_header *)syst;
+ status = sfi_tb_verify_checksum(table, length);
+ if (status) {
+ pr_err(PREFIX "SYST checksum error!!\n");
+ sfi_unmap_memory(table, length);
+ return status;
+ }
+
+ /* Calculate the number of tables */
+ tbl_cnt = (length - sizeof(struct sfi_table_header)) / sizeof(u64);
+ paddr = (u64 *) syst->pentry;
+
+ sfi_tblist.count = 1;
+ sfi_tblist.tables[0].address = syst_addr;
+ sfi_tblist.tables[0].pointer = NULL;
+ memcpy(&sfi_tblist.tables[0].header,
+ syst, sizeof(struct sfi_table_header));
+
+ /* 3. save all tables info to the global sfi_tblist structure */
+ for (i = 1; i <= tbl_cnt; i++)
+ sfi_tb_install_table(*paddr++, 0);
+
+ sfi_unmap_memory(syst, length);
+
+ return 0;
+}
+
+
+/*
+ * The OS finds the System Table by searching 16-byte boundaries between physical
+ * address 0x000E0000 and 0x000FFFFF. The OS shall search this region starting at the
+ * low address and shall stop searching when the 1st valid SFI System Table is found.
+ */
+static __init unsigned long sfi_find_syst(void)
+{
+ unsigned long offset, len;
+ void *start;
+
+ len = SFI_SYST_SEARCH_END - SFI_SYST_SEARCH_BEGIN;
+ start = sfi_map_memory(SFI_SYST_SEARCH_BEGIN, len);
+ if (!start)
+ return 0;
+
+ for (offset = 0; offset < len; offset += 16) {
+ struct sfi_table_header *syst;
+
+ syst = (struct sfi_table_header *)(start + offset);
+
+ if (strncmp(syst->signature, SFI_SIG_SYST, SFI_SIGNATURE_SIZE))
+ continue;
+
+ if (!sfi_tb_verify_checksum(syst, syst->length)) {
+ sfi_unmap_memory(start, len);
+ return SFI_SYST_SEARCH_BEGIN + offset;
+ }
+ }
+
+ sfi_unmap_memory(start, len);
+ return 0;
+}
+
+int __init sfi_table_init(void)
+{
+ unsigned long syst_paddr;
+ int status;
+
+ /* set up the SFI table array */
+ sfi_tblist.tables = sfi_initial_tables;
+ sfi_tblist.size = SFI_MAX_TABLES;
+
+ syst_paddr = sfi_find_syst();
+ if (!syst_paddr) {
+ pr_warning(PREFIX "No system table\n");
+ goto err_exit;
+ }
+
+ status = sfi_tb_parse_syst(syst_paddr);
+ if (status)
+ goto err_exit;
+
+ return 0;
+err_exit:
+ disable_sfi();
+ return -1;
+}
+
+static void sfi_realloc_tblist(void)
+{
+ int size;
+ struct sfi_table_desc *table;
+
+ size = (sfi_tblist.count + 8) * sizeof(struct sfi_table_desc);
+ table = kzalloc(size, GFP_KERNEL);
+ if (!table) {
+ disable_sfi();
+ return;
+ }
+
+ memcpy(table, sfi_tblist.tables,
+ sfi_tblist.count * sizeof(struct sfi_table_desc));
+ sfi_tblist.tables = table;
+ return;
+}
+
+int __init sfi_init(void)
+{
+ if(!acpi_disabled){
+ disable_sfi();
+ return -1;
+ }
+
+ if(sfi_disabled)
+ return -1;
+
+ pr_info(PREFIX "Simple Firmware Interface v0.5\n");
+
+ if (sfi_table_init())
+ return -1;
+
+ return sfi_platform_init();
+}
+/* after most of the system is up, abandon the static array */
+void __init sfi_init_late(void)
+{
+ if (sfi_disabled)
+ return;
+ sfi_tbl_permanant_mapped = 1;
+ sfi_realloc_tblist();
+}
+
+static int __init sfi_parse_cmdline(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
+
+ if (!strcmp(arg, "off"))
+ sfi_disabled = 1;
+
+ return 0;
+}
+early_param("sfi", sfi_parse_cmdline);
diff --git a/drivers/sfi/sfi_core.h b/drivers/sfi/sfi_core.h
new file mode 100644
index 0000000..36703b0
--- /dev/null
+++ b/drivers/sfi/sfi_core.h
@@ -0,0 +1,63 @@
+/* sfi_core.h Simple Firmware Interface, internal header */
+
+/*
+ * Copyright (C) 2009, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+struct sfi_table_desc {
+ struct sfi_table_header header; /* copy of the headef info */
+ struct sfi_table_header *pointer;
+ u64 address;
+ u32 flags;
+};
+
+/* SFI internal root SYSTem table */
+struct sfi_internal_syst {
+ struct sfi_table_desc *tables;
+ u32 count;
+ u32 size;
+};
+
+extern int sfi_get_table(char *signature, char *oem_id, char *oem_table_id,
+ uint flags, struct sfi_table_header **out_table);
+extern void sfi_put_table(struct sfi_table_header *table);
+
+extern int sfi_acpi_init(void);
+extern struct sfi_internal_syst sfi_tblist;
+void sfi_tb_install_table(u64 address, u32 flags);
+
+#define SFI_ACPI_TABLE 1
+
--
1.6.0.6
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH 3/8] SFI: core support
2009-06-23 7:14 ` [PATCH 3/8] SFI: core support Len Brown
@ 2009-06-23 7:56 ` Ingo Molnar
2009-06-23 8:32 ` Feng Tang
2009-06-23 17:20 ` Len Brown
2009-06-23 12:32 ` Andi Kleen
1 sibling, 2 replies; 53+ messages in thread
From: Ingo Molnar @ 2009-06-23 7:56 UTC (permalink / raw)
To: Len Brown, H. Peter Anvin, Thomas Gleixner, Yinghai Lu,
Andrew Morton, Linus Torvalds
Cc: sfi-devel, linux-kernel, Feng Tang, Len Brown
> --- /dev/null
> +++ b/arch/x86/kernel/sfi.c
> +#include <linux/init.h>
> +#include <linux/efi.h>
> +#include <linux/cpumask.h>
> +#include <linux/module.h>
> +#include <linux/irq.h>
> +#include <linux/bootmem.h>
> +#include <linux/io.h>
> +#include <linux/acpi.h>
> +#include <linux/efi.h>
> +#include <linux/sfi.h>
> +
> +#include <asm/pgtable.h>
> +#include <asm/io_apic.h>
> +#include <asm/apic.h>
> +#include <asm/mpspec.h>
> +
> +#include <asm/e820.h>
> +#include <asm/setup.h>
Please try to use the include files style in arch/x86/mm/fault.c. It
is minimalistic and deterministically ordered as well, so it will
look in a pleasant way long-term too .
> +#undef PREFIX
Why undefine it? No header should set 'PREFIX' - if it does it needs
fixing.
> +#define PREFIX "SFI: "
>
> +#ifdef CONFIG_X86_LOCAL_APIC
> +static u64 sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
> +#endif
if SFI adds a 'depends on X86_LOCAL_APIC' the ugly #ifdef can be
dropped.
> +
> +extern int __init sfi_parse_xsdt(struct sfi_table_header *table);
> +static int __init sfi_parse_cpus(struct sfi_table_header *table);
> +static int __init sfi_parse_apic(struct sfi_table_header *table);
These should be in a header i guess.
> +
> +void __init __iomem *
> +arch_early_ioremap(unsigned long phys, unsigned long size)
> +{
> + return early_ioremap(phys, size);
> +}
> +
> +void __init arch_early_iounmap(void __iomem *virt, unsigned long size)
> +{
> + early_iounmap(virt, size);
> +}
Should be in a separate series and not added to sfi.c but to core
x86.
> +
> +static ulong __init sfi_early_find_syst(void)
Please use C types such as 'unsigned long'.
> +{
> + unsigned long i;
... like here.
> + char *pchar = (char *)SFI_SYST_SEARCH_BEGIN;
> +
> + for (i = 0; SFI_SYST_SEARCH_BEGIN + i < SFI_SYST_SEARCH_END; i += 16, pchar += 16) {
What does the magic constant '16' mean here?
> + if (!strncmp(SFI_SIG_SYST, pchar, SFI_SIGNATURE_SIZE))
> + return SFI_SYST_SEARCH_BEGIN + i;
> + }
> + return 0;
> +}
> +
> +/*
> + * called in a early boot phase before the paging table is created,
> + * setup a mmap table in e820 format
> + */
> +int __init sfi_init_memory_map(void)
> +{
> + struct sfi_table_simple *syst, *mmapt;
> + struct sfi_mem_entry *mentry;
> + unsigned long long start, end, size;
> + int i, num, type, tbl_cnt;
> + u64 *pentry;
> +
> + if (sfi_disabled)
> + return -1;
> +
> + /* first search the syst table */
> + syst = (struct sfi_table_simple *)sfi_early_find_syst();
why doesnt sfi_early_find_syst() return the proper type?
> + if (!syst)
> + return -1;
> +
> + tbl_cnt = (syst->header.length - sizeof(struct sfi_table_header)) / sizeof(u64);
> + pentry = syst->pentry;
> +
> + /* walk through the syst to search the mmap table */
> + mmapt = NULL;
> + for (i = 0; i < tbl_cnt; i++) {
> + if (!strncmp(SFI_SIG_MMAP, (char *)(u32)*pentry, 4)) {
> + mmapt = (struct sfi_table_simple *)(u32)*pentry;
> + break;
> + }
> + pentry++;
> + }
> + if (!mmapt)
> + return -1;
> +
> + /* refer copy_e820_memory() */
> + num = SFI_GET_ENTRY_NUM(mmapt, sfi_mem_entry);
> + mentry = (struct sfi_mem_entry *)mmapt->pentry;
> + for (i = 0; i < num; i++) {
> + start = mentry->phy_start;
> + size = mentry->pages << PAGE_SHIFT;
> + end = start + size;
> +
> + if (start > end)
> + return -1;
> +
> + pr_debug(PREFIX "start = 0x%08x end = 0x%08x type = %d\n",
> + (u32)start, (u32)end, mentry->type);
> +
> + /* translate SFI mmap type to E820 map type */
> + switch (mentry->type) {
> + case EFI_CONVENTIONAL_MEMORY:
> + type = E820_RAM;
> + break;
> + case EFI_MEMORY_MAPPED_IO:
> + case EFI_UNUSABLE_MEMORY:
> + case EFI_RUNTIME_SERVICES_DATA:
> + mentry++;
> + continue;
> + default:
> + type = E820_RESERVED;
> + }
> +
> + e820_add_region(start, size, type);
> + mentry++;
> + }
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_X86_LOCAL_APIC
> +void __init mp_sfi_register_lapic_address(u64 address)
> +{
> + mp_lapic_addr = (unsigned long) address;
mp_lapic_addr should have the proper type i guess.
> +
> + set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
> +
> + if (boot_cpu_physical_apicid == -1U)
> + boot_cpu_physical_apicid = read_apic_id();
> +
> + pr_info(PREFIX "Boot CPU = %d\n", boot_cpu_physical_apicid);
Should be pr_debug() i guess - we know the boot CPU from a number of
other places already.
> +}
> +
> +/* All CPUs enumerated by SFI must be present and enabled */
> +void __cpuinit mp_sfi_register_lapic(u8 id)
> +{
> + struct mpc_cpu cpu;
> + int boot_cpu = 0;
> +
> + if (MAX_APICS - id <= 0) {
> + printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
> + id, MAX_APICS);
> + return;
> + }
> +
> + if (id == boot_cpu_physical_apicid)
> + boot_cpu = 1;
> +
> + cpu.type = MP_PROCESSOR;
> + cpu.apicid = id;
> + cpu.apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
> + cpu.cpuflag = CPU_ENABLED;
> + cpu.cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
> + cpu.cpufeature = (boot_cpu_data.x86 << 8) |
> + (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
> + cpu.featureflag = boot_cpu_data.x86_capability[0];
> + cpu.reserved[0] = 0;
> + cpu.reserved[1] = 0;
Nice trick - MP-spec is still useful after all.
> +
> + generic_processor_info(id, cpu.apicver);
> +}
> +
> +static int __init sfi_parse_cpus(struct sfi_table_header *table)
> +{
> + struct sfi_table_simple *sb;
> + struct sfi_cpu_table_entry *pentry;
> + int i;
> + int cpu_num;
> +
> + BUG_ON(!table);
Can this happen? If yes, is a boot crash the best answer?
> + sb = (struct sfi_table_simple *)table;
> +
> + cpu_num = SFI_GET_ENTRY_NUM(sb, sfi_cpu_table_entry);
> + pentry = (struct sfi_cpu_table_entry *) sb->pentry;
(unneeded space character)
> +
> + for (i = 0; i < cpu_num; i++) {
> + mp_sfi_register_lapic(pentry->apicid);
> + pentry++;
> + }
> +
> + smp_found_config = 1;
> + return 0;
> +}
> +#endif /* CONFIG_X86_LOCAL_APIC */
> +
> +#ifdef CONFIG_X86_IO_APIC
Should SFI add 'depends on X86_IO_APIC' perhaps? (or do you
anticipate IO-APIC-less implementations?)
> +static struct mp_ioapic_routing {
> + int apic_id;
> + int gsi_base;
> + int gsi_end;
> + u32 pin_programmed[4];
> +} mp_ioapic_routing[MAX_IO_APICS];
Data structures should be defined at the top of the .c file, not
hidden in the middle.
> +
> +/* refer acpi/boot.c */
> +static u8 __init uniq_ioapic_id(u8 id)
> +{
> +#ifdef CONFIG_X86_32
> + if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
> + !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
> + return io_apic_get_unique_id(nr_ioapics, id);
> + else
> + return id;
> +#else
> + int i;
> + DECLARE_BITMAP(used, 256);
> + bitmap_zero(used, 256);
Newline needed after local variabe definition blocks.
> + for (i = 0; i < nr_ioapics; i++) {
> + struct mpc_ioapic *ia = &mp_ioapics[i];
> + __set_bit(ia->apicid, used);
> + }
> + if (!test_bit(id, used))
> + return id;
> + return find_first_zero_bit(used, 256);
> +#endif
> +}
Why is the 32-bit and 64-bit version so different? Please unify
first before adding new functionality.
> +
> +
> +void __init mp_sfi_register_ioapic(u8 id, u32 paddr)
> +{
> + int idx = 0;
> + int tmpid;
> + static u32 gsi_base;
> +
> + if (nr_ioapics >= MAX_IO_APICS) {
> + printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
> + "(found %d)\n", MAX_IO_APICS, nr_ioapics);
> + panic("Recompile kernel with bigger MAX_IO_APICS!\n");
> + }
> + if (!paddr) {
> + printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
> + " found in MADT table, skipping!\n");
> + return;
> + }
> +
> + idx = nr_ioapics;
> +
> + mp_ioapics[idx].type = MP_IOAPIC;
> + mp_ioapics[idx].flags = MPC_APIC_USABLE;
> + mp_ioapics[idx].apicaddr = paddr;
> +
> + set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, paddr);
> + tmpid = uniq_ioapic_id(id);
> + if (tmpid == -1)
> + return;
> +
> + mp_ioapics[idx].apicid = tmpid;
> +#ifdef CONFIG_X86_32
> + mp_ioapics[idx].apicver = io_apic_get_version(idx);
> +#else
> + mp_ioapics[idx].apicver = 0;
> +#endif
Could this #ifdef be eliminated?
> +
> + pr_info(PREFIX "IOAPIC[%d]: apic_id %d, version %d, address 0x%x\n",
> + idx, mp_ioapics[idx].apicid,
> + mp_ioapics[idx].apicver, (u32)mp_ioapics[idx].apicaddr);
> + /*
> + * Build basic GSI lookup table to facilitate gsi->io_apic lookups
> + * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
> + */
> + mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].apicid;
> + mp_ioapic_routing[idx].gsi_base = gsi_base;
> + mp_ioapic_routing[idx].gsi_end = gsi_base +
> + io_apic_get_redir_entries(idx);
> + gsi_base = mp_ioapic_routing[idx].gsi_end + 1;
> + pr_info(PREFIX "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
> + "GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
> + mp_ioapics[idx].apicver, (u32)mp_ioapics[idx].apicaddr,
> + mp_ioapic_routing[idx].gsi_base,
> + mp_ioapic_routing[idx].gsi_end);
> +
> + nr_ioapics++;
> +}
> +
> +static int __init sfi_parse_apic(struct sfi_table_header *table)
> +{
> + struct sfi_table_simple *sb;
> + struct sfi_apic_table_entry *pentry;
> + int i, num;
> +
> + BUG_ON(!table);
Same as comment above - is this case anticipated? If yes, is a crash
the best answer?
> + sb = (struct sfi_table_simple *)table;
> +
> + num = SFI_GET_ENTRY_NUM(sb, sfi_apic_table_entry);
> + pentry = (struct sfi_apic_table_entry *) sb->pentry;
> + for (i = 0; i < num; i++) {
> + mp_sfi_register_ioapic(i, pentry->phy_addr);
> + pentry++;
> + }
> +
> + WARN_ON(pic_mode);
> + pic_mode = 0;
If this warning can occor, please use WARN() instead with a
user-parseable message.
> + return 0;
> +}
> +#endif /* CONFIG_X86_IO_APIC */
> +
> +/*
> + * sfi_platform_init(): register lapics & io-apics
> + */
> +int __init sfi_platform_init(void)
> +{
> +#ifdef CONFIG_X86_LOCAL_APIC
> + mp_sfi_register_lapic_address(sfi_lapic_addr);
> + sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, 0, sfi_parse_cpus);
> +#endif
> +#ifdef CONFIG_X86_IO_APIC
> + sfi_table_parse(SFI_SIG_APIC, NULL, NULL, 0, sfi_parse_apic);
> +#endif
Both of these #ifdefs would go away with the 'depends on'
suggestions i made above.
Also, sfi_parse_apic() should be named sfr_parse_ioapic() ?
> + return 0;
> +}
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 1266ead..c3e39b5 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -11,6 +11,7 @@ obj-$(CONFIG_PARISC) += parisc/
> obj-$(CONFIG_RAPIDIO) += rapidio/
> obj-y += video/
> obj-$(CONFIG_ACPI) += acpi/
> +obj-$(CONFIG_SFI) += sfi/
> # PnP must come after ACPI since it will eventually need to check if acpi
> # was used and do nothing if so
> obj-$(CONFIG_PNP) += pnp/
> diff --git a/drivers/sfi/Makefile b/drivers/sfi/Makefile
> new file mode 100644
> index 0000000..f176470
> --- /dev/null
> +++ b/drivers/sfi/Makefile
> @@ -0,0 +1 @@
> +obj-y += sfi_core.o
> diff --git a/drivers/sfi/sfi_core.c b/drivers/sfi/sfi_core.c
> new file mode 100644
> index 0000000..0a9b72d
> --- /dev/null
> +++ b/drivers/sfi/sfi_core.c
> @@ -0,0 +1,403 @@
> +/* sfi_core.c Simple Firmware Interface - core internals */
> +
> +/*
> + * Copyright (C) 2009, Intel Corp.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions, and the following disclaimer,
> + * without modification.
> + * 2. Redistributions in binary form must reproduce at minimum a disclaimer
> + * substantially similar to the "NO WARRANTY" disclaimer below
> + * ("Disclaimer") and any redistribution must be conditioned upon
> + * including a substantially similar Disclaimer requirement for further
> + * binary redistribution.
> + * 3. Neither the names of the above-listed copyright holders nor the names
> + * of any contributors may be used to endorse or promote products derived
> + * from this software without specific prior written permission.
> + *
> + * Alternatively, this software may be distributed under the terms of the
> + * GNU General Public License ("GPL") version 2 as published by the Free
> + * Software Foundation.
> + *
> + * NO WARRANTY
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
> + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGES.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/smp.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +#include <linux/irq.h>
> +#include <linux/errno.h>
> +#include <linux/sfi.h>
> +#include <linux/bootmem.h>
> +#include <linux/module.h>
> +#include <asm/pgtable.h>
> +#include "sfi_core.h"
> +
> +#undef PREFIX
> +#define PREFIX "SFI: "
> +
> +int sfi_disabled;
Should be __read_mostly? (other read-mostly variables below too i
guess)
> +EXPORT_SYMBOL(sfi_disabled);
> +
> +#define SFI_MAX_TABLES 64
Kernels we release will live 5-10 years easily - new hw is never
expected to have more than 64 tables?
> +struct sfi_internal_syst sfi_tblist;
> +static struct sfi_table_desc sfi_initial_tables[SFI_MAX_TABLES] __initdata;
> +
> +/*
> + * flag for whether using ioremap() to map the sfi tables, if yes
> + * each table only need be mapped once, otherwise each arch's
> + * early_ioremap and early_iounmap should be used each time a
> + * table is visited
> + */
> +static u32 sfi_tbl_permanant_mapped;
> +
> +static void __iomem *sfi_map_memory(u32 phys, u32 size)
> +{
> + if (!phys || !size)
> + return NULL;
> +
> + if (sfi_tbl_permanant_mapped)
> + return ioremap((unsigned long)phys, size);
> + else
> + return arch_early_ioremap((unsigned long)phys, size);
> +}
> +
> +static void sfi_unmap_memory(void __iomem *virt, u32 size)
> +{
> + if (!virt || !size)
> + return;
> +
> + if (sfi_tbl_permanant_mapped)
> + iounmap(virt);
> + else
> + arch_early_iounmap(virt, size);
> +}
> +
That's a disgusting facility. Should be separated out ...
> +static void sfi_print_table_header(u32 address,
> + struct sfi_table_header *header)
> +{
> + pr_info(PREFIX
> + "%4.4s %08lX, %04X (r%d %6.6s %8.8s)\n",
> + header->signature, (unsigned long)address,
> + header->length, header->revision, header->oem_id,
> + header->oem_table_id);
> +}
Why do we need the type cast above?
> +
> +static u8 sfi_checksum_table(u8 *buffer, u32 length)
> +{
> + u8 sum = 0;
> +
> + while (length--)
> + sum += *buffer++;
> + return sum;
> +}
> +
> +/* Verifies if the table checksums is zero */
> +static int sfi_tb_verify_checksum(struct sfi_table_header *table, u32 length)
> +{
> + u8 checksum;
> +
> + checksum = sfi_checksum_table((u8 *)table, length);
Why not declare sfi_checksum_table() with a void * input type
instead and lose the cast above? That way a potential source of bugs
gets found. (say accidentally passing in an 'address' to the
function instead of a table pointer)
> + if (checksum) {
> + pr_warning(PREFIX
> + "Incorrect checksum in table [%4.4s] - %2.2X,"
> + " should be %2.2X\n", table->signature,
> + table->checksum, (u8)(table->checksum - checksum));
> + return -1;
> + }
> + return 0;
> +}
> +
> + /* find the right table based on signaure, return the mapped table */
> +int sfi_get_table(char *signature, char *oem_id, char *oem_table_id,
> + unsigned int flags, struct sfi_table_header **out_table)
> +{
> + struct sfi_table_desc *tdesc;
> + struct sfi_table_header *th;
> + u32 i;
> +
> + if (!signature || !out_table)
> + return -1;
> +
> + /* Walk the global SFI table list */
> + for (i = 0; i < sfi_tblist.count; i++) {
> + tdesc = &sfi_tblist.tables[i];
> + th = &tdesc->header;
> +
> + if ((flags & SFI_ACPI_TABLE) != (tdesc->flags & SFI_ACPI_TABLE))
> + continue;
> +
> + if (strncmp(th->signature, signature, SFI_SIGNATURE_SIZE))
> + continue;
> +
> + if (oem_id && strncmp(th->oem_id, oem_id, SFI_OEM_ID_SIZE))
> + continue;
> +
> + if (oem_table_id && strncmp(th->oem_table_id, oem_table_id,
> + SFI_OEM_TABLE_ID_SIZE))
> + continue;
> +
> + if (!tdesc->pointer) {
> + tdesc->pointer = sfi_map_memory(tdesc->address,
> + th->length);
> + if (!tdesc->pointer)
> + return -ENOMEM;
> + }
> + *out_table = tdesc->pointer;
> +
> + if (!sfi_tbl_permanant_mapped)
> + tdesc->pointer = NULL;
> +
> + return 0;
> + }
> +
> + return -1;
> +}
> +
> +void sfi_put_table(struct sfi_table_header *table)
> +{
> + if (!sfi_tbl_permanant_mapped)
> + sfi_unmap_memory(table, table->length);
> +}
> +
> +/* find table with signature, run handler on it */
> +int sfi_table_parse(char *signature, char *oem_id, char* oem_table_id,
> + unsigned int flags, sfi_table_handler handler)
> +{
> + int ret = 0;
> + struct sfi_table_header *table = NULL;
> +
> + if (!handler)
> + return -EINVAL;
> +
> + sfi_get_table(signature, oem_id, oem_table_id, flags, &table);
> + if (!table)
> + return -1;
the error return is a bit unclean here. First we use -EINVAL, then
-1 - which is -EPERM which doesnt make sense. I'd suggest to return
-EINVAL or -ENOTFOUND instead of -1 - not mix the return codes like
that.
> +
> + ret = handler(table);
> + sfi_put_table(table);
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(sfi_table_parse);
> +
> +void sfi_tb_install_table(u64 addr, u32 flags)
> +{
> + struct sfi_table_header *table;
> + u32 length;
> +
> + /* only map table header before knowing actual length */
> + table = sfi_map_memory(addr, sizeof(struct sfi_table_header));
> + if (!table)
> + return;
> +
> + length = table->length;
> + sfi_unmap_memory(table, sizeof(struct sfi_table_header));
> +
> + table = sfi_map_memory(addr, length);
> + if (!table)
> + return;
> +
> + if (sfi_tb_verify_checksum(table, length))
> + goto unmap_and_exit;
> +
> + /* Initialize sfi_tblist entry */
> + sfi_tblist.tables[sfi_tblist.count].flags = flags;
> + sfi_tblist.tables[sfi_tblist.count].address = addr;
> + sfi_tblist.tables[sfi_tblist.count].pointer = NULL;
> + memcpy(&sfi_tblist.tables[sfi_tblist.count].header,
> + table, sizeof(struct sfi_table_header));
> +
> + sfi_print_table_header(addr, table);
> + sfi_tblist.count++;
> +
> +unmap_and_exit:
> + sfi_unmap_memory(table, length);
> + return;
> +}
> +
> +/*
> + * Copy system table and associated table headers to internal format
> + */
> +static int __init
> +sfi_tb_parse_syst(unsigned long syst_addr)
> +{
> + struct sfi_table_simple *syst;
> + struct sfi_table_header *table;
> + u64 *paddr;
> + u32 length, tbl_cnt;
> + int status;
> + int i;
> +
> + /* 1. map and get the total length of SYST */
> + syst = sfi_map_memory(syst_addr, sizeof(struct sfi_table_simple));
> + if (!syst)
> + return -ENOMEM;
> +
> + sfi_print_table_header(syst_addr, (struct sfi_table_header *)syst);
> + table = (struct sfi_table_header *)syst;
> + length = table->length;
> + sfi_unmap_memory(syst, sizeof(struct sfi_table_simple));
> +
> + /* 2. remap/verify the SYST and parse the number of entry */
> + syst = sfi_map_memory(syst_addr, length);
> + if (!syst)
> + return -ENOMEM;
> +
> + table = (struct sfi_table_header *)syst;
> + status = sfi_tb_verify_checksum(table, length);
> + if (status) {
> + pr_err(PREFIX "SYST checksum error!!\n");
> + sfi_unmap_memory(table, length);
> + return status;
> + }
> +
> + /* Calculate the number of tables */
> + tbl_cnt = (length - sizeof(struct sfi_table_header)) / sizeof(u64);
> + paddr = (u64 *) syst->pentry;
> +
> + sfi_tblist.count = 1;
> + sfi_tblist.tables[0].address = syst_addr;
> + sfi_tblist.tables[0].pointer = NULL;
> + memcpy(&sfi_tblist.tables[0].header,
> + syst, sizeof(struct sfi_table_header));
> +
> + /* 3. save all tables info to the global sfi_tblist structure */
> + for (i = 1; i <= tbl_cnt; i++)
> + sfi_tb_install_table(*paddr++, 0);
> +
> + sfi_unmap_memory(syst, length);
> +
> + return 0;
> +}
> +
> +
> +/*
> + * The OS finds the System Table by searching 16-byte boundaries between physical
> + * address 0x000E0000 and 0x000FFFFF. The OS shall search this region starting at the
> + * low address and shall stop searching when the 1st valid SFI System Table is found.
(Way-) overlong lines here.
> + */
> +static __init unsigned long sfi_find_syst(void)
> +{
> + unsigned long offset, len;
> + void *start;
> +
> + len = SFI_SYST_SEARCH_END - SFI_SYST_SEARCH_BEGIN;
> + start = sfi_map_memory(SFI_SYST_SEARCH_BEGIN, len);
> + if (!start)
> + return 0;
> +
> + for (offset = 0; offset < len; offset += 16) {
> + struct sfi_table_header *syst;
> +
> + syst = (struct sfi_table_header *)(start + offset);
No need for the cast here - void pointers are unitype.
> +
> + if (strncmp(syst->signature, SFI_SIG_SYST, SFI_SIGNATURE_SIZE))
> + continue;
(one too many tabs)
> +
> + if (!sfi_tb_verify_checksum(syst, syst->length)) {
> + sfi_unmap_memory(start, len);
> + return SFI_SYST_SEARCH_BEGIN + offset;
> + }
> + }
> +
> + sfi_unmap_memory(start, len);
> + return 0;
> +}
> +
> +int __init sfi_table_init(void)
> +{
> + unsigned long syst_paddr;
> + int status;
> +
> + /* set up the SFI table array */
> + sfi_tblist.tables = sfi_initial_tables;
> + sfi_tblist.size = SFI_MAX_TABLES;
> +
> + syst_paddr = sfi_find_syst();
> + if (!syst_paddr) {
> + pr_warning(PREFIX "No system table\n");
> + goto err_exit;
> + }
> +
> + status = sfi_tb_parse_syst(syst_paddr);
> + if (status)
> + goto err_exit;
> +
> + return 0;
> +err_exit:
> + disable_sfi();
> + return -1;
> +}
> +
> +static void sfi_realloc_tblist(void)
> +{
> + int size;
> + struct sfi_table_desc *table;
> +
> + size = (sfi_tblist.count + 8) * sizeof(struct sfi_table_desc);
magic, unexplained 8.
> + table = kzalloc(size, GFP_KERNEL);
> + if (!table) {
> + disable_sfi();
> + return;
> + }
> +
> + memcpy(table, sfi_tblist.tables,
> + sfi_tblist.count * sizeof(struct sfi_table_desc));
> + sfi_tblist.tables = table;
> + return;
> +}
> +
> +int __init sfi_init(void)
> +{
> + if(!acpi_disabled){
> + disable_sfi();
> + return -1;
> + }
> +
> + if(sfi_disabled)
> + return -1;
Coding style problems.
> +
> + pr_info(PREFIX "Simple Firmware Interface v0.5\n");
> +
> + if (sfi_table_init())
> + return -1;
> +
> + return sfi_platform_init();
> +}
> +/* after most of the system is up, abandon the static array */
> +void __init sfi_init_late(void)
> +{
> + if (sfi_disabled)
> + return;
> + sfi_tbl_permanant_mapped = 1;
> + sfi_realloc_tblist();
> +}
> +
> +static int __init sfi_parse_cmdline(char *arg)
> +{
> + if (!arg)
> + return -EINVAL;
> +
> + if (!strcmp(arg, "off"))
> + sfi_disabled = 1;
> +
> + return 0;
> +}
> +early_param("sfi", sfi_parse_cmdline);
> diff --git a/drivers/sfi/sfi_core.h b/drivers/sfi/sfi_core.h
> new file mode 100644
> index 0000000..36703b0
> --- /dev/null
> +++ b/drivers/sfi/sfi_core.h
> @@ -0,0 +1,63 @@
> +/* sfi_core.h Simple Firmware Interface, internal header */
> +
> +/*
> + * Copyright (C) 2009, Intel Corp.
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions, and the following disclaimer,
> + * without modification.
> + * 2. Redistributions in binary form must reproduce at minimum a disclaimer
> + * substantially similar to the "NO WARRANTY" disclaimer below
> + * ("Disclaimer") and any redistribution must be conditioned upon
> + * including a substantially similar Disclaimer requirement for further
> + * binary redistribution.
> + * 3. Neither the names of the above-listed copyright holders nor the names
> + * of any contributors may be used to endorse or promote products derived
> + * from this software without specific prior written permission.
> + *
> + * Alternatively, this software may be distributed under the terms of the
> + * GNU General Public License ("GPL") version 2 as published by the Free
> + * Software Foundation.
> + *
> + * NO WARRANTY
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
> + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGES.
> + */
> +
> +struct sfi_table_desc {
> + struct sfi_table_header header; /* copy of the headef info */
s/headef/header
> + struct sfi_table_header *pointer;
> + u64 address;
> + u32 flags;
> +};
> +
> +/* SFI internal root SYSTem table */
> +struct sfi_internal_syst {
> + struct sfi_table_desc *tables;
> + u32 count;
> + u32 size;
> +};
i'd suggest using the structure definition style you use in
arch/x86/kernel/sfi.c:
> +struct sfi_table_desc {
> + struct sfi_table_header header; /* copy of the headef info */
> + struct sfi_table_header *pointer;
> + u64 address;
> + u32 flags;
> +};
> +
> +extern int sfi_get_table(char *signature, char *oem_id, char *oem_table_id,
> + uint flags, struct sfi_table_header **out_table);
> +extern void sfi_put_table(struct sfi_table_header *table);
> +
> +extern int sfi_acpi_init(void);
> +extern struct sfi_internal_syst sfi_tblist;
> +void sfi_tb_install_table(u64 address, u32 flags);
> +
> +#define SFI_ACPI_TABLE 1
In general, nice stuff - basically SFI is cleanly implemented ACPI
tables without any of the run-code-in-acpi-tables complications,
right?
Ingo
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH 3/8] SFI: core support
2009-06-23 7:56 ` Ingo Molnar
@ 2009-06-23 8:32 ` Feng Tang
2009-06-23 9:03 ` Ingo Molnar
2009-06-23 17:20 ` Len Brown
1 sibling, 1 reply; 53+ messages in thread
From: Feng Tang @ 2009-06-23 8:32 UTC (permalink / raw)
To: Ingo Molnar
Cc: Len Brown, H. Peter Anvin, Thomas Gleixner, Yinghai Lu,
Andrew Morton, Linus Torvalds, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org, Brown, Len
On Tue, 23 Jun 2009 15:56:43 +0800
Ingo Molnar <mingo@elte.hu> wrote:
> >
> > +#ifdef CONFIG_X86_LOCAL_APIC
> > +static u64 sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
> > +#endif
>
> if SFI adds a 'depends on X86_LOCAL_APIC' the ugly #ifdef can be
> dropped.
When Len designed the SFI spec, he considered the possibility of being used by
multiple archs, so we chose not to add a x86 dependency, though adding these
#ifdef does make code ugly :P
> > +{
> > + unsigned long i;
>
> ... like here.
>
> > + char *pchar = (char *)SFI_SYST_SEARCH_BEGIN;
> > +
> > + for (i = 0; SFI_SYST_SEARCH_BEGIN + i < SFI_SYST_SEARCH_END;
> > i += 16, pchar += 16) {
>
> What does the magic constant '16' mean here?
My bad not puting clear comments here, the SFI spec defines SYST table starts
at a 16-byte boundary
> > +
> > +static int __init sfi_parse_apic(struct sfi_table_header *table)
> > +{
> > + struct sfi_table_simple *sb;
> > + struct sfi_apic_table_entry *pentry;
> > + int i, num;
> > +
> > + BUG_ON(!table);
>
> Same as comment above - is this case anticipated? If yes, is a crash
> the best answer?
Yes, usually table won't be NULL
> > +
> > +#define SFI_ACPI_TABLE 1
>
> In general, nice stuff - basically SFI is cleanly implemented ACPI
> tables without any of the run-code-in-acpi-tables complications,
> right?
Thanks for the comments, I really got inspired :). The expectation for SFI
is to be able to run cleanly with CONFIG_ACPI=n, and it works fine on some
intel platform.
Thanks,
Feng
>
> Ingo
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH 3/8] SFI: core support
2009-06-23 8:32 ` Feng Tang
@ 2009-06-23 9:03 ` Ingo Molnar
2009-06-23 9:15 ` Feng Tang
0 siblings, 1 reply; 53+ messages in thread
From: Ingo Molnar @ 2009-06-23 9:03 UTC (permalink / raw)
To: Feng Tang
Cc: Len Brown, H. Peter Anvin, Thomas Gleixner, Yinghai Lu,
Andrew Morton, Linus Torvalds, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org, Brown, Len
* Feng Tang <feng.tang@intel.com> wrote:
> On Tue, 23 Jun 2009 15:56:43 +0800
> Ingo Molnar <mingo@elte.hu> wrote:
>
>
> > >
> > > +#ifdef CONFIG_X86_LOCAL_APIC
> > > +static u64 sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
> > > +#endif
> >
> > if SFI adds a 'depends on X86_LOCAL_APIC' the ugly #ifdef can be
> > dropped.
>
> When Len designed the SFI spec, he considered the possibility of
> being used by multiple archs, so we chose not to add a x86
> dependency, though adding these
> #ifdef does make code ugly :P
But the file i commented on is arch/x86/kernel/sfi.c, not
drivers/sfi/.
Those #ifdefs arent _that_ bad (and are used elsewhere in x86 code
too) - but generally some effort should be spent in new code on
trying to eliminate them.
> > In general, nice stuff - basically SFI is cleanly implemented
> > ACPI tables without any of the run-code-in-acpi-tables
> > complications, right?
>
> Thanks for the comments, I really got inspired :). The expectation
> for SFI is to be able to run cleanly with CONFIG_ACPI=n, and it
> works fine on some intel platform.
Ok, cool!
Ingo
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH 3/8] SFI: core support
2009-06-23 9:03 ` Ingo Molnar
@ 2009-06-23 9:15 ` Feng Tang
0 siblings, 0 replies; 53+ messages in thread
From: Feng Tang @ 2009-06-23 9:15 UTC (permalink / raw)
To: Ingo Molnar
Cc: Len Brown, H. Peter Anvin, Thomas Gleixner, Yinghai Lu,
Andrew Morton, Linus Torvalds, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org
On Tue, 23 Jun 2009 17:03:47 +0800
Ingo Molnar <mingo@elte.hu> wrote:
>
> * Feng Tang <feng.tang@intel.com> wrote:
>
> > On Tue, 23 Jun 2009 15:56:43 +0800
> > Ingo Molnar <mingo@elte.hu> wrote:
> >
> >
> > > >
> > > > +#ifdef CONFIG_X86_LOCAL_APIC
> > > > +static u64 sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
> > > > +#endif
> > >
> > > if SFI adds a 'depends on X86_LOCAL_APIC' the ugly #ifdef can be
> > > dropped.
> >
> > When Len designed the SFI spec, he considered the possibility of
> > being used by multiple archs, so we chose not to add a x86
> > dependency, though adding these
> > #ifdef does make code ugly :P
>
> But the file i commented on is arch/x86/kernel/sfi.c, not
> drivers/sfi/.
Now got your point, then we can think about adding a SFI_X86 Kconfig
option specifically for x86 platform, which has dependency over the
LAPIC/IO_APIC
Thanks,
Feng
>
> Those #ifdefs arent _that_ bad (and are used elsewhere in x86 code
> too) - but generally some effort should be spent in new code on
> trying to eliminate them.
>
> > > In general, nice stuff - basically SFI is cleanly implemented
> > > ACPI tables without any of the run-code-in-acpi-tables
> > > complications, right?
> >
> > Thanks for the comments, I really got inspired :). The expectation
> > for SFI is to be able to run cleanly with CONFIG_ACPI=n, and it
> > works fine on some intel platform.
>
> Ok, cool!
>
> Ingo
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH 3/8] SFI: core support
2009-06-23 7:56 ` Ingo Molnar
2009-06-23 8:32 ` Feng Tang
@ 2009-06-23 17:20 ` Len Brown
2009-06-23 19:20 ` Ingo Molnar
1 sibling, 1 reply; 53+ messages in thread
From: Len Brown @ 2009-06-23 17:20 UTC (permalink / raw)
To: Ingo Molnar
Cc: H. Peter Anvin, Thomas Gleixner, Yinghai Lu, Andrew Morton,
Linus Torvalds, sfi-devel, Linux Kernel Mailing List, Feng Tang,
Andi Kleen
Re: #define PREFIX "SFI: "
The SFI code uses all pr_info/debug/warning/err format
and so it looks like the way to go is like this;
#define KMSG_COMPONENT "SFI"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
and get rid of the PREFIX stuff in the actual messages.
Is that the recommended way to go these days?
thanks,
-Len Brown, Intel Open Soruce Technolgy Center
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH 3/8] SFI: core support
2009-06-23 17:20 ` Len Brown
@ 2009-06-23 19:20 ` Ingo Molnar
0 siblings, 0 replies; 53+ messages in thread
From: Ingo Molnar @ 2009-06-23 19:20 UTC (permalink / raw)
To: Len Brown
Cc: H. Peter Anvin, Thomas Gleixner, Yinghai Lu, Andrew Morton,
Linus Torvalds, sfi-devel, Linux Kernel Mailing List, Feng Tang,
Andi Kleen
* Len Brown <lenb@kernel.org> wrote:
> Re: #define PREFIX "SFI: "
>
> The SFI code uses all pr_info/debug/warning/err format
> and so it looks like the way to go is like this;
>
> #define KMSG_COMPONENT "SFI"
> #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
>
> and get rid of the PREFIX stuff in the actual messages.
> Is that the recommended way to go these days?
Yeah, overloadig pr_fmt looks entirely correct and per design. That
will make it even cleaner.
Ingo
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH 3/8] SFI: core support
2009-06-23 7:14 ` [PATCH 3/8] SFI: core support Len Brown
2009-06-23 7:56 ` Ingo Molnar
@ 2009-06-23 12:32 ` Andi Kleen
2009-06-23 16:57 ` Len Brown
2009-06-24 3:34 ` Feng Tang
1 sibling, 2 replies; 53+ messages in thread
From: Andi Kleen @ 2009-06-23 12:32 UTC (permalink / raw)
To: Len Brown; +Cc: sfi-devel, linux-kernel, Feng Tang, Len Brown
Len Brown <lenb@kernel.org> writes:
> +static ulong __init sfi_early_find_syst(void)
> +{
> + unsigned long i;
> + char *pchar = (char *)SFI_SYST_SEARCH_BEGIN;
> +
> + for (i = 0; SFI_SYST_SEARCH_BEGIN + i < SFI_SYST_SEARCH_END; i += 16, pchar += 16) {
> + if (!strncmp(SFI_SIG_SYST, pchar, SFI_SIGNATURE_SIZE))
> + return SFI_SYST_SEARCH_BEGIN + i;
Such additional memory scans are always a bit risky, e.g. if there's
stray hardware there. Has it been verified that existing kernels
already scan this area?
> + mmapt = NULL;
> + for (i = 0; i < tbl_cnt; i++) {
> + if (!strncmp(SFI_SIG_MMAP, (char *)(u32)*pentry, 4)) {
> + mmapt = (struct sfi_table_simple *)(u32)*pentry;
> + break;
> + }
> + pentry++;
> + }
> + if (!mmapt)
> + return -1;
printk here?
> +
> + /* refer copy_e820_memory() */
> + num = SFI_GET_ENTRY_NUM(mmapt, sfi_mem_entry);
> + mentry = (struct sfi_mem_entry *)mmapt->pentry;
> + for (i = 0; i < num; i++) {
> + start = mentry->phy_start;
> + size = mentry->pages << PAGE_SHIFT;
> + end = start + size;
> +
> + if (start > end)
> + return -1;
> +
> + pr_debug(PREFIX "start = 0x%08x end = 0x%08x type = %d\n",
> + (u32)start, (u32)end, mentry->type);
> +
> + /* translate SFI mmap type to E820 map type */
> + switch (mentry->type) {
> + case EFI_CONVENTIONAL_MEMORY:
> + type = E820_RAM;
> + break;
> + case EFI_MEMORY_MAPPED_IO:
> + case EFI_UNUSABLE_MEMORY:
> + case EFI_RUNTIME_SERVICES_DATA:
> + mentry++;
Surely UNUSTABLE and RUNTIME_SERVICES should be added somewhere to the resources,
otherwise MMIO allocation might put something there.
> + }
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_X86_LOCAL_APIC
> +void __init mp_sfi_register_lapic_address(u64 address)
> +{
> + mp_lapic_addr = (unsigned long) address;
> +
> + set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
> +
> + if (boot_cpu_physical_apicid == -1U)
> + boot_cpu_physical_apicid = read_apic_id();
> +
> + pr_info(PREFIX "Boot CPU = %d\n", boot_cpu_physical_apicid);
That's the same what ACPI does, isn't it? Some code sharing
would be good.
> +static int __init sfi_parse_cpus(struct sfi_table_header *table)
> +{
> + struct sfi_table_simple *sb;
> + struct sfi_cpu_table_entry *pentry;
> + int i;
> + int cpu_num;
> +
> + BUG_ON(!table);
Another useless BUG_ON. Some more below too.
> + sb = (struct sfi_table_simple *)table;
> +
> + cpu_num = SFI_GET_ENTRY_NUM(sb, sfi_cpu_table_entry);
> + pentry = (struct sfi_cpu_table_entry *) sb->pentry;
> +
> + for (i = 0; i < cpu_num; i++) {
> + mp_sfi_register_lapic(pentry->apicid);
> + pentry++;
> + }
Array overflow checking?
> + mp_ioapics[idx].apicver = 0;
> +#endif
> +
> + pr_info(PREFIX "IOAPIC[%d]: apic_id %d, version %d, address 0x%x\n",
> + idx, mp_ioapics[idx].apicid,
> + mp_ioapics[idx].apicver, (u32)mp_ioapics[idx].apicaddr);
> + /*
> + * Build basic GSI lookup table to facilitate gsi->io_apic lookups
> + * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
> + */
> + mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].apicid;
> + mp_ioapic_routing[idx].gsi_base = gsi_base;
> + mp_ioapic_routing[idx].gsi_end = gsi_base +
> + io_apic_get_redir_entries(idx);
> + gsi_base = mp_ioapic_routing[idx].gsi_end + 1;
> + pr_info(PREFIX "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
> + "GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
> + mp_ioapics[idx].apicver, (u32)mp_ioapics[idx].apicaddr,
> + mp_ioapic_routing[idx].gsi_base,
> + mp_ioapic_routing[idx].gsi_end);
That printk should be dependent on the runtime apic verbosity level?
> +
> +/*
> + * flag for whether using ioremap() to map the sfi tables, if yes
> + * each table only need be mapped once, otherwise each arch's
> + * early_ioremap and early_iounmap should be used each time a
> + * table is visited
> + */
> +static u32 sfi_tbl_permanant_mapped;
permanant is a typo?
> +
> +static void __iomem *sfi_map_memory(u32 phys, u32 size)
> +{
> + if (!phys || !size)
> + return NULL;
> +
> + if (sfi_tbl_permanant_mapped)
> + return ioremap((unsigned long)phys, size);
> + else
> + return arch_early_ioremap((unsigned long)phys, size);
> +}
imho it would be cleaner if the callers just called these functions
directly. Are the !phys !size checks really needed?
> +
> +void sfi_tb_install_table(u64 addr, u32 flags)
> +{
> + struct sfi_table_header *table;
> + u32 length;
> +
> + /* only map table header before knowing actual length */
> + table = sfi_map_memory(addr, sizeof(struct sfi_table_header));
> + if (!table)
> + return;
> +
> + length = table->length;
> + sfi_unmap_memory(table, sizeof(struct sfi_table_header));
> +
> + table = sfi_map_memory(addr, length);
> + if (!table)
> + return;
Since the mappings are always 4K you would only need to remap
if the size is > PAGE_SIZE
> +
> + if (sfi_tb_verify_checksum(table, length))
> + goto unmap_and_exit;
> +
> + /* Initialize sfi_tblist entry */
> + sfi_tblist.tables[sfi_tblist.count].flags = flags;
> + sfi_tblist.tables[sfi_tblist.count].address = addr;
> + sfi_tblist.tables[sfi_tblist.count].pointer = NULL;
> + memcpy(&sfi_tblist.tables[sfi_tblist.count].header,
> + table, sizeof(struct sfi_table_header));
To be honest I'm not sure why this list exists at all.
Is it that difficult to just rewalk the firmware supplied
table as needed?
-andi
--
ak@linux.intel.com -- Speaking for myself only.
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH 3/8] SFI: core support
2009-06-23 12:32 ` Andi Kleen
@ 2009-06-23 16:57 ` Len Brown
2009-06-24 3:34 ` Feng Tang
1 sibling, 0 replies; 53+ messages in thread
From: Len Brown @ 2009-06-23 16:57 UTC (permalink / raw)
To: Andi Kleen; +Cc: sfi-devel, Linux Kernel Mailing List, Feng Tang
On Tue, 23 Jun 2009, Andi Kleen wrote:
> Len Brown <lenb@kernel.org> writes:
>
> > +static ulong __init sfi_early_find_syst(void)
> > +{
> > + unsigned long i;
> > + char *pchar = (char *)SFI_SYST_SEARCH_BEGIN;
> > +
> > + for (i = 0; SFI_SYST_SEARCH_BEGIN + i < SFI_SYST_SEARCH_END; i += 16, pchar += 16) {
> > + if (!strncmp(SFI_SIG_SYST, pchar, SFI_SIGNATURE_SIZE))
> > + return SFI_SYST_SEARCH_BEGIN + i;
>
>
> Such additional memory scans are always a bit risky, e.g. if there's
> stray hardware there. Has it been verified that existing kernels
> already scan this area?
Yes, SFI is the same as ACPI here (actually, a proper sub-set).
Note that the UEFI folks have suggested that on UEFI systems,
that they hand us the address like they can do for ACPI,
and we'll probably add that at some point.
thanks,
-Len Brown, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH 3/8] SFI: core support
2009-06-23 12:32 ` Andi Kleen
2009-06-23 16:57 ` Len Brown
@ 2009-06-24 3:34 ` Feng Tang
2009-06-24 7:12 ` Andi Kleen
1 sibling, 1 reply; 53+ messages in thread
From: Feng Tang @ 2009-06-24 3:34 UTC (permalink / raw)
To: Andi Kleen
Cc: Len Brown, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org, Brown, Len
On Tue, 23 Jun 2009 20:32:56 +0800
Andi Kleen <andi@firstfloor.org> wrote:
> > +static void __iomem *sfi_map_memory(u32 phys, u32 size)
> > +{
> > + if (!phys || !size)
> > + return NULL;
> > +
> > + if (sfi_tbl_permanant_mapped)
>
>
>
> > + return ioremap((unsigned long)phys, size);
> > + else
> > + return arch_early_ioremap((unsigned long)phys,
> > size); +}
>
> imho it would be cleaner if the callers just called these functions
> directly. Are the !phys !size checks really needed?
Andi,
Thanks for many good comments, will address them.
For this question, this sfi_map_memory() may get called before and after
the ioremap() is ready, so we add a permanent flag to judge the
environment and chose the right API automatically. e.g. after system is
booted, cpu freq driver will implicitly call this API to get freq info
>
>
> > +
> > +void sfi_tb_install_table(u64 addr, u32 flags)
> > +{
> > + struct sfi_table_header *table;
> > + u32 length;
> > +
> > + /* only map table header before knowing actual length */
> > + table = sfi_map_memory(addr, sizeof(struct
> > sfi_table_header));
> > + if (!table)
> > + return;
> > +
> > + length = table->length;
> > + sfi_unmap_memory(table, sizeof(struct sfi_table_header));
> > +
> > + table = sfi_map_memory(addr, length);
> > + if (!table)
> > + return;
>
>
> Since the mappings are always 4K you would only need to remap
> if the size is > PAGE_SIZE
yes, some of the table may be in one page, but some may not start at page
boundary and cross pages, we do it this way as this map/unmap/remap/unmap
routine only happen few times in boot phase.
>
> > +
> > + if (sfi_tb_verify_checksum(table, length))
> > + goto unmap_and_exit;
> > +
> > + /* Initialize sfi_tblist entry */
> > + sfi_tblist.tables[sfi_tblist.count].flags = flags;
> > + sfi_tblist.tables[sfi_tblist.count].address = addr;
> > + sfi_tblist.tables[sfi_tblist.count].pointer = NULL;
> > + memcpy(&sfi_tblist.tables[sfi_tblist.count].header,
> > + table, sizeof(struct sfi_table_header));
>
> To be honest I'm not sure why this list exists at all.
> Is it that difficult to just rewalk the firmware supplied
> table as needed?
Currently, there are about 10 SFI tables (more are expected), and most of
them will be parsed in driver initialization phase, like timer/cpu idle/
cpu frequency/rtc/system wake driver. Using a global list may save some
system overhead
Thanks,
Feng
>
>
> -andi
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH 3/8] SFI: core support
2009-06-24 3:34 ` Feng Tang
@ 2009-06-24 7:12 ` Andi Kleen
2009-06-24 7:40 ` Feng Tang
0 siblings, 1 reply; 53+ messages in thread
From: Andi Kleen @ 2009-06-24 7:12 UTC (permalink / raw)
To: Feng Tang
Cc: Andi Kleen, Len Brown, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org, Brown, Len
On Wed, Jun 24, 2009 at 11:34:40AM +0800, Feng Tang wrote:
>
> > > +static void __iomem *sfi_map_memory(u32 phys, u32 size)
> > > +{
> > > + if (!phys || !size)
> > > + return NULL;
> > > +
> > > + if (sfi_tbl_permanant_mapped)
> >
> >
> >
> > > + return ioremap((unsigned long)phys, size);
> > > + else
> > > + return arch_early_ioremap((unsigned long)phys,
> > > size); +}
> >
> > imho it would be cleaner if the callers just called these functions
> > directly. Are the !phys !size checks really needed?
>
> Andi,
>
> Thanks for many good comments, will address them.
>
> For this question, this sfi_map_memory() may get called before and after
> the ioremap() is ready, so we add a permanent flag to judge the
Yes, but the callers should know this and they can call the right
function. I suspect only very few callers will need the early
variant.
> environment and chose the right API automatically. e.g. after system is
> booted, cpu freq driver will implicitly call this API to get freq info
cpufreq driver shouldn't be initialized before ioremap
> >
> > Since the mappings are always 4K you would only need to remap
> > if the size is > PAGE_SIZE
>
> yes, some of the table may be in one page, but some may not start at page
> boundary and cross pages, we do it this way as this map/unmap/remap/unmap
> routine only happen few times in boot phase.
The TLB flushes tend to be a few thousand cycles at least.
It's not much, but with all the recent focus on faster boot times it's
still better to not write unnecessarily inefficient initialization code.
>
> >
> > > +
> > > + if (sfi_tb_verify_checksum(table, length))
> > > + goto unmap_and_exit;
> > > +
> > > + /* Initialize sfi_tblist entry */
> > > + sfi_tblist.tables[sfi_tblist.count].flags = flags;
> > > + sfi_tblist.tables[sfi_tblist.count].address = addr;
> > > + sfi_tblist.tables[sfi_tblist.count].pointer = NULL;
> > > + memcpy(&sfi_tblist.tables[sfi_tblist.count].header,
> > > + table, sizeof(struct sfi_table_header));
> >
> > To be honest I'm not sure why this list exists at all.
> > Is it that difficult to just rewalk the firmware supplied
> > table as needed?
>
> Currently, there are about 10 SFI tables (more are expected), and most of
> them will be parsed in driver initialization phase, like timer/cpu idle/
> cpu frequency/rtc/system wake driver. Using a global list may save some
> system overhead
Walking the tables as they are laid out in memory should be quite
equivalent to walking a list, shouldn't it?
It would be only a relatively small simplification agreed, but if you're
claiming to do a "Simple Firmware Interface" imho you should try
to make it as simple possible, and that includes not setting up
redundant data structures.
-Andi
--
ak@linux.intel.com -- Speaking for myself only.
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH 3/8] SFI: core support
2009-06-24 7:12 ` Andi Kleen
@ 2009-06-24 7:40 ` Feng Tang
2009-06-24 7:55 ` Andi Kleen
0 siblings, 1 reply; 53+ messages in thread
From: Feng Tang @ 2009-06-24 7:40 UTC (permalink / raw)
To: Andi Kleen
Cc: Len Brown, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org
On Wed, 24 Jun 2009 15:12:20 +0800
Andi Kleen <andi@firstfloor.org> wrote:
> On Wed, Jun 24, 2009 at 11:34:40AM +0800, Feng Tang wrote:
> >
> > > > +static void __iomem *sfi_map_memory(u32 phys, u32 size)
> > > > +{
> > > > + if (!phys || !size)
> > > > + return NULL;
> > > > +
> > > > + if (sfi_tbl_permanant_mapped)
> > > > + return ioremap((unsigned long)phys, size);
> > > > + else
> > > > + return arch_early_ioremap((unsigned long)phys,
> > > > size); +}
> > >
> > > imho it would be cleaner if the callers just called these
> > > functions directly. Are the !phys !size checks really needed?
> >
> > Andi,
> >
> > Thanks for many good comments, will address them.
> >
> > For this question, this sfi_map_memory() may get called before and
> > after the ioremap() is ready, so we add a permanent flag to judge
> > the
>
> Yes, but the callers should know this and they can call the right
> function. I suspect only very few callers will need the early
> variant.
>
There is one sfi_table_parse() API, which is a SFI core function, it is exported
out and used in both boot phase (parsing cpu/ioapic) and later driver phase
(parsing idle/freq ...), when it get called, it doesn't know in which phase it get
called, and need such a flag to judge.
> > environment and chose the right API automatically. e.g. after
> > system is booted, cpu freq driver will implicitly call this API to
> > get freq info
>
> cpufreq driver shouldn't be initialized before ioremap
Right, it called the sfi_table_parse() after ioremap is ready.
>
> > >
> > > Since the mappings are always 4K you would only need to remap
> > > if the size is > PAGE_SIZE
> >
> > yes, some of the table may be in one page, but some may not start
> > at page boundary and cross pages, we do it this way as this
> > map/unmap/remap/unmap routine only happen few times in boot phase.
>
> The TLB flushes tend to be a few thousand cycles at least.
>
> It's not much, but with all the recent focus on faster boot times it's
> still better to not write unnecessarily inefficient initialization
> code.
good point, will take care of it
>
> >
> > >
> > > > +
> > > > + if (sfi_tb_verify_checksum(table, length))
> > > > + goto unmap_and_exit;
> > > > +
> > > > + /* Initialize sfi_tblist entry */
> > > > + sfi_tblist.tables[sfi_tblist.count].flags = flags;
> > > > + sfi_tblist.tables[sfi_tblist.count].address = addr;
> > > > + sfi_tblist.tables[sfi_tblist.count].pointer = NULL;
> > > > + memcpy(&sfi_tblist.tables[sfi_tblist.count].header,
> > > > + table, sizeof(struct sfi_table_header));
> > >
> > > To be honest I'm not sure why this list exists at all.
> > > Is it that difficult to just rewalk the firmware supplied
> > > table as needed?
> >
> > Currently, there are about 10 SFI tables (more are expected), and
> > most of them will be parsed in driver initialization phase, like
> > timer/cpu idle/ cpu frequency/rtc/system wake driver. Using a
> > global list may save some system overhead
>
> Walking the tables as they are laid out in memory should be quite
> equivalent to walking a list, shouldn't it?
>
> It would be only a relatively small simplification agreed, but if
> you're claiming to do a "Simple Firmware Interface" imho you should
> try to make it as simple possible, and that includes not setting up
> redundant data structures.
understand your concern, but to walk a list we still need have some global
parameter like SYST address, and do the map/unmap and checksum work.
another reason for the global sfi_table_desc[] is, we only do some time ioremap
for each table and save the mapped address for future use. this idea is
borrowed from ACPI table handling.
Thanks,
Feng
>
> -Andi
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH 3/8] SFI: core support
2009-06-24 7:40 ` Feng Tang
@ 2009-06-24 7:55 ` Andi Kleen
0 siblings, 0 replies; 53+ messages in thread
From: Andi Kleen @ 2009-06-24 7:55 UTC (permalink / raw)
To: Feng Tang
Cc: Andi Kleen, Len Brown, sfi-devel@simplefirmware.org,
linux-kernel@vger.kernel.org
> understand your concern, but to walk a list we still need have some global
> parameter like SYST address, and do the map/unmap and checksum work.
You just keep it mapped always. And the checksums only need to
be checked once at the beginning. If there's a checksum error
anywhere it's better to complete disable SFI
-Andi
--
ak@linux.intel.com -- Speaking for myself only.
^ permalink raw reply [flat|nested] 53+ messages in thread
* [PATCH 4/8] SFI: Hook boot-time initialization
2009-06-23 7:13 ` [PATCH 1/8] SFI: Simple Firmware Interface - new Linux sub-system Len Brown
2009-06-23 7:14 ` [PATCH 2/8] SFI: include/linux/sfi.h Len Brown
2009-06-23 7:14 ` [PATCH 3/8] SFI: core support Len Brown
@ 2009-06-23 7:14 ` Len Brown
2009-06-23 7:14 ` [PATCH 5/8] SFI: Hook e820 memory map initialization Len Brown
` (4 subsequent siblings)
7 siblings, 0 replies; 53+ messages in thread
From: Len Brown @ 2009-06-23 7:14 UTC (permalink / raw)
To: sfi-devel, linux-kernel; +Cc: Feng Tang, Len Brown
From: Feng Tang <feng.tang@intel.com>
Signed-off-by: Feng Tang <feng.tang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/x86/kernel/setup.c | 3 +++
init/main.c | 2 ++
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index b415843..e2e6794 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -27,6 +27,7 @@
#include <linux/screen_info.h>
#include <linux/ioport.h>
#include <linux/acpi.h>
+#include <linux/sfi.h>
#include <linux/apm_bios.h>
#include <linux/initrd.h>
#include <linux/bootmem.h>
@@ -952,6 +953,8 @@ void __init setup_arch(char **cmdline_p)
*/
acpi_boot_init();
+ sfi_init();
+
#if defined(CONFIG_X86_MPPARSE) || defined(CONFIG_X86_VISWS)
/*
* get boot-time SMP configuration:
diff --git a/init/main.c b/init/main.c
index f1b9f0f..36333c7 100644
--- a/init/main.c
+++ b/init/main.c
@@ -65,6 +65,7 @@
#include <linux/idr.h>
#include <linux/ftrace.h>
#include <linux/async.h>
+#include <linux/sfi.h>
#include <trace/boot.h>
#include <asm/io.h>
@@ -688,6 +689,7 @@ asmlinkage void __init start_kernel(void)
check_bugs();
acpi_early_init(); /* before LAPIC and SMP init */
+ sfi_init_late();
ftrace_init();
--
1.6.0.6
^ permalink raw reply related [flat|nested] 53+ messages in thread* [PATCH 5/8] SFI: Hook e820 memory map initialization
2009-06-23 7:13 ` [PATCH 1/8] SFI: Simple Firmware Interface - new Linux sub-system Len Brown
` (2 preceding siblings ...)
2009-06-23 7:14 ` [PATCH 4/8] SFI: Hook boot-time initialization Len Brown
@ 2009-06-23 7:14 ` Len Brown
2009-06-23 7:14 ` [PATCH 6/8] SFI: add ACPI extensions Len Brown
` (3 subsequent siblings)
7 siblings, 0 replies; 53+ messages in thread
From: Len Brown @ 2009-06-23 7:14 UTC (permalink / raw)
To: sfi-devel, linux-kernel; +Cc: Feng Tang, Len Brown
From: Feng Tang <feng.tang@intel.com>
Signed-off-by: Feng Tang <feng.tang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/x86/kernel/e820.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 0062813..f5f5ff2 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -20,6 +20,7 @@
#include <linux/pfn.h>
#include <linux/suspend.h>
#include <linux/firmware-map.h>
+#include <linux/sfi.h>
#include <asm/pgtable.h>
#include <asm/page.h>
@@ -1403,6 +1404,10 @@ char *__init default_machine_specific_memory_setup(void)
< 0) {
u64 mem_size;
+ /* if SFI mmap table exists, use SFI to setup e820 mmap */
+ if (!sfi_init_memory_map())
+ return "SFI";
+
/* compare results from other methods and take the greater */
if (boot_params.alt_mem_k
< boot_params.screen_info.ext_mem_k) {
--
1.6.0.6
^ permalink raw reply related [flat|nested] 53+ messages in thread* [PATCH 6/8] SFI: add ACPI extensions
2009-06-23 7:13 ` [PATCH 1/8] SFI: Simple Firmware Interface - new Linux sub-system Len Brown
` (3 preceding siblings ...)
2009-06-23 7:14 ` [PATCH 5/8] SFI: Hook e820 memory map initialization Len Brown
@ 2009-06-23 7:14 ` Len Brown
2009-06-23 12:18 ` Andi Kleen
2009-06-23 7:14 ` [PATCH 7/8] SFI, PCI: Hook MMCONFIG Len Brown
` (2 subsequent siblings)
7 siblings, 1 reply; 53+ messages in thread
From: Len Brown @ 2009-06-23 7:14 UTC (permalink / raw)
To: sfi-devel, linux-kernel; +Cc: Feng Tang, Len Brown
From: Feng Tang <feng.tang@intel.com>
Extend SFI to access standard ACPI tables
such as the PCI MCFG using sfi_acpi_table_parse().
Note that SFI runs only with acpi_disabled=1,
but is independent of CONFIG_ACPI.
Signed-off-by: Feng Tang <feng.tang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
drivers/acpi/tables.c | 3 +
drivers/sfi/Makefile | 2 +
drivers/sfi/sfi_acpi.c | 94 +++++++++++++++++++++++++++++++++++++++++++
include/acpi/acpi_drivers.h | 3 +
include/linux/acpi.h | 5 +-
include/linux/sfi_acpi.h | 56 +++++++++++++++++++++++++
6 files changed, 161 insertions(+), 2 deletions(-)
create mode 100644 drivers/sfi/sfi_acpi.c
create mode 100644 include/linux/sfi_acpi.h
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 646d39c..921746f 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -277,6 +277,9 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler)
struct acpi_table_header *table = NULL;
acpi_size tbl_size;
+ if (acpi_disabled)
+ return 1;
+
if (!handler)
return -EINVAL;
diff --git a/drivers/sfi/Makefile b/drivers/sfi/Makefile
index f176470..2343732 100644
--- a/drivers/sfi/Makefile
+++ b/drivers/sfi/Makefile
@@ -1 +1,3 @@
+obj-y += sfi_acpi.o
obj-y += sfi_core.o
+
diff --git a/drivers/sfi/sfi_acpi.c b/drivers/sfi/sfi_acpi.c
new file mode 100644
index 0000000..f972785
--- /dev/null
+++ b/drivers/sfi/sfi_acpi.c
@@ -0,0 +1,94 @@
+/* sfi_acpi.c Simple Firmware Interface - ACPI extensions */
+
+/*
+ * Copyright (C) 2009, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <linux/acpi.h>
+#include <linux/kernel.h>
+#include <linux/sfi.h>
+#include "sfi_core.h"
+
+#undef PREFIX
+#define PREFIX "SFI: "
+
+/*
+ * SFI can access ACPI-defined tables via an optional ACPI XSDT.
+ *
+ * This allows re-use, and avoids re-definition, of standard tables.
+ * For example, the "MCFG" table is defined by PCI, reserved by ACPI,
+ * and is expected to be present many SFI-only systems.
+ */
+
+/*
+ * sfi_acpi_parse_xsdt()
+ *
+ * Parse the ACPI XSDT for later access by sfi_acpi_table_parse().
+ */
+static int __init sfi_acpi_parse_xsdt(struct sfi_table_header *table)
+{
+ int num_entries, i;
+
+ struct acpi_table_xsdt *xsdt = (struct acpi_table_xsdt *) table;
+
+ BUG_ON(!xsdt);
+
+ num_entries = (xsdt->header.length - sizeof(struct acpi_table_header) /
+ sizeof(u64));
+
+ pr_debug(PREFIX "XSDT has %d entries\n", num_entries);
+
+ for (i = 0; i < num_entries; i++)
+ sfi_tb_install_table(xsdt->table_offset_entry[i], SFI_ACPI_TABLE);
+
+ return 0;
+}
+
+int sfi_acpi_init()
+{
+ sfi_table_parse(SFI_SIG_XSDT, NULL, NULL, 0, sfi_acpi_parse_xsdt);
+ return 0;
+}
+/*
+ * sfi_acpi_table_parse()
+ */
+int sfi_acpi_table_parse(char *signature, char *oem_id, char* oem_table_id,
+ unsigned int flags, acpi_table_handler handler)
+{
+ return sfi_table_parse(signature, oem_id, oem_table_id, SFI_ACPI_TABLE,
+ (sfi_table_handler)handler);
+}
+
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index 0352c8f..5d84a17 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -29,6 +29,8 @@
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
+#ifdef CONFIG_ACPI
+
#define ACPI_MAX_STRING 80
/*
@@ -157,4 +159,5 @@ static inline void unregister_hotplug_dock_device(acpi_handle handle)
}
#endif
+#endif /* CONFIG_ACPI */
#endif /*__ACPI_DRIVERS_H__*/
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index bf17681..be418f1 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -27,7 +27,6 @@
#include <linux/ioport.h> /* for struct resource */
-#ifdef CONFIG_ACPI
#ifndef _LINUX
#define _LINUX
@@ -43,6 +42,9 @@
#include <asm/acpi.h>
#include <linux/dmi.h>
+typedef int (*acpi_table_handler) (struct acpi_table_header *table);
+
+#ifdef CONFIG_ACPI
enum acpi_irq_model_id {
ACPI_IRQ_MODEL_PIC = 0,
@@ -74,7 +76,6 @@ enum acpi_address_range_id {
/* Table Handlers */
-typedef int (*acpi_table_handler) (struct acpi_table_header *table);
typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end);
diff --git a/include/linux/sfi_acpi.h b/include/linux/sfi_acpi.h
new file mode 100644
index 0000000..7a49380
--- /dev/null
+++ b/include/linux/sfi_acpi.h
@@ -0,0 +1,56 @@
+/* sfi.h Simple Firmware Interface */
+
+/*
+ * Copyright (C) 2009, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef _LINUX_SFI_ACPI_H
+#define _LINUX_SFI_ACPI_H
+
+#ifdef CONFIG_SFI
+#include <linux/acpi.h> /* acpi_table_handler */
+
+int sfi_acpi_table_parse(char *signature, char *oem_id, char* oem_table_id,
+ uint flag, acpi_table_handler handler);
+
+#else /* !CONFIG_SFI */
+
+static inline int sfi_acpi_table_parse(char *signature, char *oem_id, char* oem_table_id,
+ unsigned int flags, acpi_table_handler handler) { return -1; }
+
+#endif /* CONFIG_SFI */
+
+#endif /*_LINUX_SFI_ACPI_H*/
--
1.6.0.6
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH 6/8] SFI: add ACPI extensions
2009-06-23 7:14 ` [PATCH 6/8] SFI: add ACPI extensions Len Brown
@ 2009-06-23 12:18 ` Andi Kleen
2009-06-23 16:51 ` Len Brown
0 siblings, 1 reply; 53+ messages in thread
From: Andi Kleen @ 2009-06-23 12:18 UTC (permalink / raw)
To: Len Brown; +Cc: sfi-devel, linux-kernel, Feng Tang, Len Brown
Len Brown <lenb@kernel.org> writes:
>
> diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
> index 646d39c..921746f 100644
> --- a/drivers/acpi/tables.c
> +++ b/drivers/acpi/tables.c
> @@ -277,6 +277,9 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler)
> struct acpi_table_header *table = NULL;
> acpi_size tbl_size;
>
> + if (acpi_disabled)
> + return 1;
> +
This seems like a weird place to hook this in. Shouldn't that be somewhere else, more
high level?
> +#include <linux/acpi.h>
> +#include <linux/kernel.h>
> +#include <linux/sfi.h>
> +#include "sfi_core.h"
> +
> +#undef PREFIX
Nobody should set PREFIX in headers? If they do better fix the headers.
> + * sfi_acpi_parse_xsdt()
> + *
> + * Parse the ACPI XSDT for later access by sfi_acpi_table_parse().
> + */
> +static int __init sfi_acpi_parse_xsdt(struct sfi_table_header *table)
> +{
> + int num_entries, i;
> +
> + struct acpi_table_xsdt *xsdt = (struct acpi_table_xsdt *) table;
> +
> + BUG_ON(!xsdt);
Seems like a pointless BUG_ON, the NULL pointer reference next to it is
obvious enough.
> +
> + num_entries = (xsdt->header.length - sizeof(struct acpi_table_header) /
> + sizeof(u64));
> +
> + pr_debug(PREFIX "XSDT has %d entries\n", num_entries);
> +
> + for (i = 0; i < num_entries; i++)
> + sfi_tb_install_table(xsdt->table_offset_entry[i], SFI_ACPI_TABLE);
Shouldn't this have some more sanity checking, e.g. for overflows?
-Andi
--
ak@linux.intel.com -- Speaking for myself only.
^ permalink raw reply [flat|nested] 53+ messages in thread* Re: [PATCH 6/8] SFI: add ACPI extensions
2009-06-23 12:18 ` Andi Kleen
@ 2009-06-23 16:51 ` Len Brown
0 siblings, 0 replies; 53+ messages in thread
From: Len Brown @ 2009-06-23 16:51 UTC (permalink / raw)
To: Andi Kleen; +Cc: sfi-devel, linux-kernel, Feng Tang, Len Brown
On Tue, 23 Jun 2009, Andi Kleen wrote:
> Len Brown <lenb@kernel.org> writes:
> > diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
> > @@ -277,6 +277,9 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler)
> > + if (acpi_disabled)
> > + return 1;
> This seems like a weird place to hook this in. Shouldn't that be somewhere else, more
> high level?
acpi_table_parse() is actually a high-level API available to drivers.
Today, drivers tend to test acpi_disabled on their own,
which may be too high level...
The catalyst for this change, IIR, was the PCI code calling
and not checking the return value:
--- a/arch/x86/pci/mmconfig-shared.c
...
@@ -606,7 +607,8 @@ static void __init __pci_mmcfg_init(int early)
...
- acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
+ if (acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg))
+ sfi_acpi_table_parse(ACPI_SIG_MCFG, NULL, NULL, 0, pci_parse_mcfg);
...
> > + num_entries = (xsdt->header.length - sizeof(struct acpi_table_header) /
> > + sizeof(u64));
> > +
> > + pr_debug(PREFIX "XSDT has %d entries\n", num_entries);
> > +
> > + for (i = 0; i < num_entries; i++)
> > + sfi_tb_install_table(xsdt->table_offset_entry[i], SFI_ACPI_TABLE);
>
> Shouldn't this have some more sanity checking, e.g. for overflows?
good observation. Although we did already check the signature and
checksum, I don't see that we yet have a sanity check either here
or in sfi_tb_install_table() itself.
thanks,
-Len
^ permalink raw reply [flat|nested] 53+ messages in thread
* [PATCH 7/8] SFI, PCI: Hook MMCONFIG
2009-06-23 7:13 ` [PATCH 1/8] SFI: Simple Firmware Interface - new Linux sub-system Len Brown
` (4 preceding siblings ...)
2009-06-23 7:14 ` [PATCH 6/8] SFI: add ACPI extensions Len Brown
@ 2009-06-23 7:14 ` Len Brown
2009-06-23 7:14 ` [PATCH 8/8] SFI: expose IO-APIC routines to SFI, not just ACPI Len Brown
2009-06-23 7:23 ` [PATCH 1/8] SFI: Simple Firmware Interface - new Linux sub-system Ingo Molnar
7 siblings, 0 replies; 53+ messages in thread
From: Len Brown @ 2009-06-23 7:14 UTC (permalink / raw)
To: sfi-devel, linux-kernel; +Cc: Feng Tang, Len Brown
From: Feng Tang <feng.tang@intel.com>
Logically, if ACPI table parsing doesn't find the MCFG,
then try SFI. In reality, the systemw will be in either
ACPI or SFI mode, so only one of these routines will run.
Signed-off-by: Feng Tang <feng.tang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/x86/Kconfig | 2 +-
arch/x86/pci/mmconfig-shared.c | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 06341a5..1143088 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1838,7 +1838,7 @@ config PCI_DIRECT
config PCI_MMCONFIG
def_bool y
- depends on X86_32 && PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
+ depends on X86_32 && PCI && (ACPI || SFI) && (PCI_GOMMCONFIG || PCI_GOANY)
config PCI_OLPC
def_bool y
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 712443e..c09683d 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -13,6 +13,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/acpi.h>
+#include <linux/sfi_acpi.h>
#include <linux/bitmap.h>
#include <linux/sort.h>
#include <asm/e820.h>
@@ -606,7 +607,8 @@ static void __init __pci_mmcfg_init(int early)
}
if (!known_bridge)
- acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
+ if (acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg))
+ sfi_acpi_table_parse(ACPI_SIG_MCFG, NULL, NULL, 0, pci_parse_mcfg);
pci_mmcfg_reject_broken(early);
--
1.6.0.6
^ permalink raw reply related [flat|nested] 53+ messages in thread* [PATCH 8/8] SFI: expose IO-APIC routines to SFI, not just ACPI
2009-06-23 7:13 ` [PATCH 1/8] SFI: Simple Firmware Interface - new Linux sub-system Len Brown
` (5 preceding siblings ...)
2009-06-23 7:14 ` [PATCH 7/8] SFI, PCI: Hook MMCONFIG Len Brown
@ 2009-06-23 7:14 ` Len Brown
2009-06-23 7:58 ` Ingo Molnar
2009-06-23 7:23 ` [PATCH 1/8] SFI: Simple Firmware Interface - new Linux sub-system Ingo Molnar
7 siblings, 1 reply; 53+ messages in thread
From: Len Brown @ 2009-06-23 7:14 UTC (permalink / raw)
To: sfi-devel, linux-kernel; +Cc: Feng Tang, Len Brown
From: Feng Tang <feng.tang@intel.com>
change condition from
#ifdef CONFIG_ACPI
to
#if defined(CONFIG_ACPI) || defined(CONFIG_SFI)
for several io_apic related APIs which will be used by both
ACPI and SFI.
this change will ensure the success kernel build whe
CONFIG_SFI=y and CONFIG_ACPI=n
Signed-off-by: Feng Tang <feng.tang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
---
arch/x86/include/asm/io_apic.h | 4 ++--
arch/x86/kernel/apic/io_apic.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 9d826e4..2e5ff36 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -150,13 +150,13 @@ extern int timer_through_8259;
#define io_apic_assign_pci_irqs \
(mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
-#ifdef CONFIG_ACPI
+#if defined(CONFIG_ACPI) || defined(CONFIG_SFI)
extern int io_apic_get_unique_id(int ioapic, int apic_id);
extern int io_apic_get_version(int ioapic);
extern int io_apic_get_redir_entries(int ioapic);
extern int io_apic_set_pci_routing(int ioapic, int pin, int irq,
int edge_level, int active_high_low);
-#endif /* CONFIG_ACPI */
+#endif /* CONFIG_ACPI || CONFIG_SFI */
extern int (*ioapic_renumber_irq)(int ioapic, int irq);
extern void ioapic_init_mappings(void);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 30da617..2705476 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -3904,7 +3904,7 @@ int __init arch_probe_nr_irqs(void)
ACPI-based IOAPIC Configuration
-------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI
+#if defined(CONFIG_ACPI) || defined(CONFIG_SFI)
#ifdef CONFIG_X86_32
int __init io_apic_get_unique_id(int ioapic, int apic_id)
@@ -4045,7 +4045,7 @@ int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
return 0;
}
-#endif /* CONFIG_ACPI */
+#endif /* CONFIG_ACPI || CONFIG_SFI */
/*
* This function currently is only a helper for the i386 smp boot process where
--
1.6.0.6
^ permalink raw reply related [flat|nested] 53+ messages in thread* Re: [PATCH 8/8] SFI: expose IO-APIC routines to SFI, not just ACPI
2009-06-23 7:14 ` [PATCH 8/8] SFI: expose IO-APIC routines to SFI, not just ACPI Len Brown
@ 2009-06-23 7:58 ` Ingo Molnar
0 siblings, 0 replies; 53+ messages in thread
From: Ingo Molnar @ 2009-06-23 7:58 UTC (permalink / raw)
To: Len Brown, H. Peter Anvin, Thomas Gleixner
Cc: sfi-devel, linux-kernel, Feng Tang, Len Brown
* Len Brown <lenb@kernel.org> wrote:
> From: Feng Tang <feng.tang@intel.com>
>
> change condition from
> #ifdef CONFIG_ACPI
> to
> #if defined(CONFIG_ACPI) || defined(CONFIG_SFI)
Please ivent a properly named helper Kconfig entry that expresses
that condition, instead of uglifying the source code.
Thanks,
Ingo
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [PATCH 1/8] SFI: Simple Firmware Interface - new Linux sub-system
2009-06-23 7:13 ` [PATCH 1/8] SFI: Simple Firmware Interface - new Linux sub-system Len Brown
` (6 preceding siblings ...)
2009-06-23 7:14 ` [PATCH 8/8] SFI: expose IO-APIC routines to SFI, not just ACPI Len Brown
@ 2009-06-23 7:23 ` Ingo Molnar
7 siblings, 0 replies; 53+ messages in thread
From: Ingo Molnar @ 2009-06-23 7:23 UTC (permalink / raw)
To: Len Brown, H. Peter Anvin, Thomas Gleixner
Cc: sfi-devel, linux-kernel, Len Brown, Feng Tang
* Len Brown <lenb@kernel.org> wrote:
> From: Len Brown <len.brown@intel.com>
>
> CONFIG_SFI=y enables the kernel to boot and run optimally
> on platforms that support the Simple Firmware Interface.
>
> Thanks to Jacob Pan for prototyping the initial Linux SFI support,
> and to Feng Tang for Linux bring-up and debug in emulation
> and on hardware.
>
> See http://simplefirmware.org for more information on SFI.
>
> Signed-off-by: Feng Tang <feng.tang@intel.com>
> Signed-off-by: Len Brown <len.brown@intel.com>
> ---
> Documentation/kernel-parameters.txt | 5 +++++
> MAINTAINERS | 12 ++++++++++++
> arch/x86/Kconfig | 2 ++
> drivers/sfi/Kconfig | 16 ++++++++++++++++
> 4 files changed, 35 insertions(+), 0 deletions(-)
> create mode 100644 drivers/sfi/Kconfig
Looks useful but this series needs review and acked-by from the x86
maintainers, obviously. It touches a lot of x86 details.
Ingo
^ permalink raw reply [flat|nested] 53+ messages in thread