lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 12 Nov 2009 23:48:52 +0300
From:	Cyrill Gorcunov <gorcunov@...il.com>
To:	Ingo Molnar <mingo@...e.hu>
Cc:	"Maciej W. Rozycki" <macro@...ux-mips.org>,
	Yinghai Lu <yinghai@...nel.org>, x86team <x86@...nel.org>,
	LKML <linux-kernel@...r.kernel.org>
Subject: [RFC -tip] x86,io-apic: Do not map IO-APIC direct registers twice

Please review, I didn't manage to test (emulate actually since I don't
have such a hardware) it yet (going to do so this weekend).

Meanwhile I would like to heard comments, complains and etc...
Perhaps I miss something obvious so don't hesitate to poke me.

	-- Cyrill
---
x86,io-apic: Do not map IO-APIC direct registers twice

In case if IO-APIC address is not 4K aligned (which is pretty
established by MPS-1.4) we may not fixmap they twice and
should eliminate resourse overlap in this case.

An example of a such configureation is

	http://marc.info/?l=linux-kernel&m=118114792006520

| Quoting the message
|
| IOAPIC[0]: apic_id 2, version 32, address 0xfec00000, GSI 0-23
| IOAPIC[1]: apic_id 3, version 32, address 0xfec80000, GSI 24-47
| IOAPIC[2]: apic_id 4, version 32, address 0xfec80400, GSI 48-71
| IOAPIC[3]: apic_id 5, version 32, address 0xfec84000, GSI 72-95
| IOAPIC[4]: apic_id 8, version 32, address 0xfec84400, GSI 96-119

Some io-apics are 4K aligned while others are -- 1K. We may have
the situation when next IO-APIC address (1K aligned) is following
previous 4K one. So instead of allocating new fixmap we may use already
done one.

To implement it ioapic_fixmap_shared is introduced which check if
new IO-APIC base address lays inside already mapped page.

Also insert_resourse will not fail anymore on 1K aligned io-apics.

CC: "Maciej W. Rozycki" <macro@...ux-mips.org>
CC: Yinghai Lu <yinghai@...nel.org>
Signed-off-by: Cyrill Gorcunov <gorcunov@...il.com>
---
 arch/x86/include/asm/apicdef.h    |   23 +++++++++++++++--
 arch/x86/include/asm/mpspec_def.h |    9 +++---
 arch/x86/kernel/apic/io_apic.c    |   50 +++++++++++++++++++++++++++++++-------
 arch/x86/kernel/mpparse.c         |    2 -
 4 files changed, 67 insertions(+), 17 deletions(-)

Index: linux-2.6.git/arch/x86/include/asm/apicdef.h
=====================================================================
--- linux-2.6.git.orig/arch/x86/include/asm/apicdef.h
+++ linux-2.6.git/arch/x86/include/asm/apicdef.h
@@ -1,6 +1,3 @@
-#ifndef _ASM_X86_APICDEF_H
-#define _ASM_X86_APICDEF_H
-
 /*
  * Constants for various Intel APICs. (local APIC, IOAPIC, etc.)
  *
@@ -8,9 +5,29 @@
  * Ingo Molnar <mingo@...hat.com>, 1999, 2000
  */
 
+#ifndef _ASM_X86_APICDEF_H
+#define _ASM_X86_APICDEF_H
+
 #define IO_APIC_DEFAULT_PHYS_BASE	0xfec00000
 #define	APIC_DEFAULT_PHYS_BASE		0xfee00000
 
+/*
+ * MP 1.4 specify that LAPIC must be aligned
+ * on 4K bound and IO-APIC on 1K
+ * (4K boud on IO-APIC is widely used too)
+ */
+#define APIC_PHYS_BASE_SHIFT		(12)
+#define IO_APIC_PHYS_BASE_SHIFT		(10)
+#define APIC_PHYS_BASE_MASK		(~((1U << APIC_PHYS_BASE_SHIFT) - 1))
+#define IO_APIC_PHYS_BASE_MASK		(~((1U << IO_APIC_PHYS_BASE_SHIFT) - 1))
+
+/*
+ * We assume that 1024 bytes will be more
+ * then enough in feasible feauture to cover
+ * all direct accessible IO-APIC registers
+ */
+#define IO_APIC_SLOT_SIZE		(1 << IO_APIC_PHYS_BASE_SHIFT)
+
 #define	APIC_ID		0x20
 
 #define	APIC_LVR	0x30
Index: linux-2.6.git/arch/x86/include/asm/mpspec_def.h
=====================================================================
--- linux-2.6.git.orig/arch/x86/include/asm/mpspec_def.h
+++ linux-2.6.git/arch/x86/include/asm/mpspec_def.h
@@ -1,11 +1,11 @@
-#ifndef _ASM_X86_MPSPEC_DEF_H
-#define _ASM_X86_MPSPEC_DEF_H
-
 /*
  * Structure definitions for SMP machines following the
  * Intel Multiprocessing Specification 1.1 and 1.4.
  */
 
+#ifndef _ASM_X86_MPSPEC_DEF_H
+#define _ASM_X86_MPSPEC_DEF_H
+
 /*
  * This tag identifies where the SMP configuration
  * information is.
@@ -107,7 +107,8 @@ struct mpc_bus {
 #define BUSTYPE_VME	"VME"
 #define BUSTYPE_XPRESS	"XPRESS"
 
-#define MPC_APIC_USABLE		0x01
+#define MPC_IO_APIC_USABLE	(1 << 0)
+#define MPC_IO_APIC_MAPPED	(1 << 1)
 
 struct mpc_ioapic {
 	unsigned char type;
Index: linux-2.6.git/arch/x86/kernel/apic/io_apic.c
=====================================================================
--- linux-2.6.git.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-2.6.git/arch/x86/kernel/apic/io_apic.c
@@ -4108,6 +4108,38 @@ static struct resource * __init ioapic_s
 	return res;
 }
 
+static __init int ioapic_fixmap_shared(unsigned long phys)
+{
+	unsigned long min, max;
+	int i;
+
+	/* if unpredictable change of PAGE_SHIFT happen */
+	BUILD_BUG_ON(APIC_PHYS_BASE_SHIFT != PAGE_SHIFT);
+
+	if (!(phys & ~APIC_PHYS_BASE_MASK))
+		return -1;
+
+	/*
+	 * if this get "hot-path" status we would need
+	 * more sophisticated/fast algorithm instead
+	 *
+	 * Note that we rely on BIOS that there is no
+	 * *overlapped or same* base addresses
+	 */
+	for (i = 0; i < nr_ioapics; i++) {
+		if (!(mp_ioapics[i].flags & MPC_IO_APIC_MAPPED)) {
+			pr_warning("IO-APIC: IO-APIC %d not mapped yet!\n", i);
+			break;
+		}
+		min = mp_ioapics[i].apicaddr & APIC_PHYS_BASE_MASK;
+		max = min + (PAGE_SIZE - IO_APIC_SLOT_SIZE);
+		if (phys >= min && phys <= max)
+			return i;
+	}
+
+	return -1;
+}
+
 void __init ioapic_init_mappings(void)
 {
 	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
@@ -4133,19 +4165,19 @@ void __init ioapic_init_mappings(void)
 #ifdef CONFIG_X86_32
 fake_ioapic_page:
 #endif
-			ioapic_phys = (unsigned long)
-				alloc_bootmem_pages(PAGE_SIZE);
+			ioapic_phys = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
 			ioapic_phys = __pa(ioapic_phys);
 		}
-		set_fixmap_nocache(idx, ioapic_phys);
-		apic_printk(APIC_VERBOSE,
-			    "mapped IOAPIC to %08lx (%08lx)\n",
-			    __fix_to_virt(idx), ioapic_phys);
-		idx++;
 
+		/* not mapped yet */
+		if (ioapic_fixmap_shared(ioapic_phys) == -1) {
+			set_fixmap_nocache(idx, ioapic_phys);
+			idx++;
+		}
 		ioapic_res->start = ioapic_phys;
-		ioapic_res->end = ioapic_phys + PAGE_SIZE-1;
+		ioapic_res->end	  = ioapic_phys + IO_APIC_SLOT_SIZE - 1;
 		ioapic_res++;
+		mp_ioapics[i].flags |= MPC_IO_APIC_MAPPED;
 	}
 }
 
@@ -4217,7 +4249,7 @@ void __init mp_register_ioapic(int id, u
 	idx = nr_ioapics;
 
 	mp_ioapics[idx].type = MP_IOAPIC;
-	mp_ioapics[idx].flags = MPC_APIC_USABLE;
+	mp_ioapics[idx].flags = MPC_IO_APIC_USABLE;
 	mp_ioapics[idx].apicaddr = address;
 
 	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
Index: linux-2.6.git/arch/x86/kernel/mpparse.c
=====================================================================
--- linux-2.6.git.orig/arch/x86/kernel/mpparse.c
+++ linux-2.6.git/arch/x86/kernel/mpparse.c
@@ -132,7 +132,7 @@ static int bad_ioapic(unsigned long addr
 
 static void __init MP_ioapic_info(struct mpc_ioapic *m)
 {
-	if (!(m->flags & MPC_APIC_USABLE))
+	if (!(m->flags & MPC_IO_APIC_USABLE))
 		return;
 
 	printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n",
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ