All of lore.kernel.org
 help / color / mirror / Atom feed
From: Len Brown <lenb@kernel.org>
To: x86@kernel.org, sfi-devel@simplefirmware.org,
	linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org
Cc: Feng Tang <feng.tang@intel.com>, Len Brown <len.brown@intel.com>
Subject: [PATCH 07/12] SFI: add x86 support
Date: Wed, 08 Jul 2009 00:13:53 -0400	[thread overview]
Message-ID: <4676b1fee4cae65c678754fbdecae626ac161b81.1247025117.git.len.brown@intel.com> (raw)
In-Reply-To: <1247026438-20891-1-git-send-email-lenb@kernel.org>
In-Reply-To: <8e4a93858bce74ed3080dd607aa471023f1a2737.1247025117.git.len.brown@intel.com>

From: Feng Tang <feng.tang@intel.com>

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    |  284 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/sfi/sfi_core.c   |    2 +-
 3 files changed, 286 insertions(+), 1 deletions(-)
 create mode 100644 arch/x86/kernel/sfi.c

diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 6c327b8..e430123 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -53,6 +53,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..a96ea0f
--- /dev/null
+++ b/arch/x86/kernel/sfi.c
@@ -0,0 +1,284 @@
+/*
+ *  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
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#define KMSG_COMPONENT "SFI"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/bootmem.h>
+#include <linux/cpumask.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/init.h>
+#include <linux/efi.h>
+#include <linux/irq.h>
+#include <linux/sfi.h>
+#include <linux/io.h>
+
+#include <asm/io_apic.h>
+#include <asm/pgtable.h>
+#include <asm/mpspec.h>
+#include <asm/setup.h>
+#include <asm/apic.h>
+#include <asm/e820.h>
+
+#ifdef CONFIG_X86_LOCAL_APIC
+static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
+#endif
+
+#ifdef CONFIG_X86_IO_APIC
+static struct mp_ioapic_routing {
+	int	gsi_base;
+	int	gsi_end;
+} mp_ioapic_routing[MAX_IO_APICS];
+#endif
+
+static __init struct sfi_table_simple *sfi_early_find_syst(void)
+{
+	unsigned long i;
+	char *pchar = (char *)SFI_SYST_SEARCH_BEGIN;
+
+	/* SFI spec defines the SYST starts at a 16-byte boundary */
+	for (i = 0; SFI_SYST_SEARCH_BEGIN + i < SFI_SYST_SEARCH_END; i += 16) {
+		if (!strncmp(SFI_SIG_SYST, pchar, SFI_SIGNATURE_SIZE))
+			return (struct sfi_table_simple *)
+					(SFI_SYST_SEARCH_BEGIN + i);
+
+		pchar += 16;
+	}
+	return NULL;
+}
+
+/*
+ * 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 = 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) {
+		pr_warning("could not find a valid memory map table\n");
+		return -1;
+	}
+
+	/* refer copy_e820_memory() */
+	num = SFI_GET_NUM_ENTRIES(mmapt, struct 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("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_UNUSABLE_MEMORY:
+			type = E820_UNUSABLE;
+			break;
+		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(unsigned long address)
+{
+	mp_lapic_addr = address;
+	set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
+
+	if (boot_cpu_physical_apicid == -1U)
+		boot_cpu_physical_apicid = read_apic_id();
+
+	pr_debug("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)
+{
+	int boot_cpu = 0;
+
+	if (MAX_APICS - id <= 0) {
+		pr_warning("Processor #%d invalid (max %d)\n",
+			id, MAX_APICS);
+		return;
+	}
+
+	if (id == boot_cpu_physical_apicid)
+		boot_cpu = 1;
+	pr_info("registering lapic[%d]\n", id);
+
+	generic_processor_info(id, GET_APIC_VERSION(apic_read(APIC_LVR)));
+}
+
+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;
+
+	sb = (struct sfi_table_simple *)table;
+	cpu_num = SFI_GET_NUM_ENTRIES(sb, struct 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
+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) {
+		pr_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) {
+		pr_warning("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
+
+	/*
+	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
+	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
+	 */
+	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("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_ioapic(struct sfi_table_header *table)
+{
+	struct sfi_table_simple *sb;
+	struct sfi_apic_table_entry *pentry;
+	int i, num;
+
+	sb = (struct sfi_table_simple *)table;
+	num = SFI_GET_NUM_ENTRIES(sb, struct 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(pic_mode, KERN_WARNING
+		"SFI: pic_mod shouldn't be 1 when IOAPIC table is present\n");
+	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_ioapic);
+#endif
+	return 0;
+}
diff --git a/drivers/sfi/sfi_core.c b/drivers/sfi/sfi_core.c
index f9a9849..8939215 100644
--- a/drivers/sfi/sfi_core.c
+++ b/drivers/sfi/sfi_core.c
@@ -350,7 +350,7 @@ void __init sfi_init(void)
 
 	pr_info("Simple Firmware Interface v0.7 http://simplefirmware.org\n");
 
-	if (sfi_find_syst() || sfi_parse_syst())
+	if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init())
 		disable_sfi();
 
 	return;
-- 
1.6.0.6


  parent reply	other threads:[~2009-07-08  4:14 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-07-08  4:13 [PATCH v2 for 2.6.32] SFI - Simple Firmware Interface support Len Brown
2009-07-08  4:13 ` [PATCH 01/12] SFI: Simple Firmware Interface - new MAINTAINERS entry Len Brown
2009-07-08  4:13   ` [PATCH 02/12] SFI, x86: add CONFIG_SFI Len Brown
2009-07-10  5:23     ` Ingo Molnar
2009-07-08  4:13   ` [PATCH 03/12] SFI: document boot param "sfi=off" Len Brown
2009-07-28 19:24     ` Bjorn Helgaas
2009-07-28 19:52       ` Len Brown
2009-07-08  4:13   ` [PATCH 04/12] SFI: create include/linux/sfi.h Len Brown
2009-07-10  6:48     ` Ingo Molnar
2009-07-08  4:13   ` [PATCH 05/12] SFI: add core support Len Brown
2009-07-10  7:40     ` Ingo Molnar
2009-07-08  4:13   ` [PATCH 06/12] ACPI, x86: remove ACPI dependency on some IO-APIC routines Len Brown
2009-07-10  6:51     ` Ingo Molnar
2009-07-08  4:13   ` Len Brown [this message]
2009-07-10  6:37     ` [PATCH 07/12] SFI: add x86 support Ingo Molnar
2009-07-10  6:48       ` Feng Tang
2009-07-08  4:13   ` [PATCH 08/12] SFI, x86: hook e820() for memory map initialization Len Brown
2009-07-08 21:37     ` H. Peter Anvin
2009-07-09  1:11       ` Feng Tang
2009-07-09  3:57         ` H. Peter Anvin
2009-07-08  4:13   ` [PATCH 09/12] SFI: Enable SFI to parse ACPI tables Len Brown
2009-07-10  6:10     ` Ingo Molnar
2009-07-08  4:13   ` [PATCH 10/12] ACPI: check acpi_disabled in acpi_table_parse() Len Brown
2009-07-08  4:13   ` [PATCH 11/12] SFI, PCI: Hook MMCONFIG Len Brown
2009-07-10  5:52     ` Ingo Molnar
2009-07-10  7:17       ` Feng Tang
2009-07-10 11:14         ` Ingo Molnar
2009-07-08  4:13   ` [PATCH 12/12] SFI: add boot-time initialization hooks Len Brown
2009-07-10  5:18 ` [PATCH v2 for 2.6.32] SFI - Simple Firmware Interface support Ingo Molnar
2009-07-11  1:01   ` Len Brown
2009-07-11  8:26     ` Ingo Molnar

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=4676b1fee4cae65c678754fbdecae626ac161b81.1247025117.git.len.brown@intel.com \
    --to=lenb@kernel.org \
    --cc=feng.tang@intel.com \
    --cc=len.brown@intel.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sfi-devel@simplefirmware.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

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

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