lkml.org 
[lkml]   [2003]   [Mar]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH][2.5][RFC][1/2] per-CPU IDTs
Index: linux-2.5.62-numaq/arch/i386/kernel/apic.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.62/arch/i386/kernel/apic.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 apic.c
--- linux-2.5.62-numaq/arch/i386/kernel/apic.c 18 Feb 2003 00:16:06 -0000 1.1.1.1
+++ linux-2.5.62-numaq/arch/i386/kernel/apic.c 24 Feb 2003 02:40:47 -0000
@@ -40,11 +40,11 @@
smp_intr_init();
#endif
/* self generated IPI for local APIC timer */
- set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
+ set_intr_gate_all(LOCAL_TIMER_VECTOR, apic_timer_interrupt);

/* IPI vectors for APIC spurious and error interrupts */
- set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
- set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
+ set_intr_gate_all(SPURIOUS_APIC_VECTOR, spurious_interrupt);
+ set_intr_gate_all(ERROR_APIC_VECTOR, error_interrupt);
}

/* Using APIC to generate smp_local_timer_interrupt? */
Index: linux-2.5.62-numaq/arch/i386/kernel/head.S
===================================================================
RCS file: /build/cvsroot/linux-2.5.62/arch/i386/kernel/head.S,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 head.S
--- linux-2.5.62-numaq/arch/i386/kernel/head.S 18 Feb 2003 00:16:06 -0000 1.1.1.1
+++ linux-2.5.62-numaq/arch/i386/kernel/head.S 24 Feb 2003 04:20:38 -0000
@@ -233,7 +233,7 @@
call check_x87
incb ready
lgdt cpu_gdt_descr
- lidt idt_descr
+ lidt cpu_idt_descr # we switch to the percpu IDTs later
ljmp $(__KERNEL_CS),$1f
1: movl $(__KERNEL_DS),%eax # reload all the segment registers
movl %eax,%ss # after changing gdt.
@@ -298,7 +298,7 @@
movw %dx,%ax /* selector = 0x0010 = cs */
movw $0x8E00,%dx /* interrupt gate - dpl=0, present */

- lea idt_table,%edi
+ lea cpu_idt_table,%edi
mov $256,%ecx
rp_sidt:
movl %eax,(%edi)
@@ -343,14 +343,16 @@
* segment size, and 32-bit linear address value:
*/

-.globl idt_descr
+.globl cpu_idt_descr
.globl cpu_gdt_descr

ALIGN
.word 0 # 32-bit align idt_desc.address
-idt_descr:
+cpu_idt_descr:
.word IDT_ENTRIES*8-1 # idt contains 256 entries
- .long idt_table
+ .long cpu_idt_table
+
+ .fill NR_CPUS-1,8,0

# boot GDT descriptor (later on used by CPU#0):
.word 0 # 32 bit align gdt_desc.address
Index: linux-2.5.62-numaq/arch/i386/kernel/i8259.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.62/arch/i386/kernel/i8259.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 i8259.c
--- linux-2.5.62-numaq/arch/i386/kernel/i8259.c 18 Feb 2003 00:16:06 -0000 1.1.1.1
+++ linux-2.5.62-numaq/arch/i386/kernel/i8259.c 24 Feb 2003 02:50:45 -0000
@@ -421,7 +421,7 @@
for (i = 0; i < NR_IRQS; i++) {
int vector = FIRST_EXTERNAL_VECTOR + i;
if (vector != SYSCALL_VECTOR)
- set_intr_gate(vector, interrupt[i]);
+ set_intr_gate_all(vector, interrupt[i]);
}

/* setup after call gates are initialised (usually add in
Index: linux-2.5.62-numaq/arch/i386/kernel/io_apic.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.62/arch/i386/kernel/io_apic.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 io_apic.c
--- linux-2.5.62-numaq/arch/i386/kernel/io_apic.c 18 Feb 2003 00:16:06 -0000 1.1.1.1
+++ linux-2.5.62-numaq/arch/i386/kernel/io_apic.c 24 Feb 2003 03:27:05 -0000
@@ -1020,7 +1020,7 @@
}

if (current_vector == FIRST_SYSTEM_VECTOR)
- panic("ran out of interrupt sources!");
+ panic("ran out of interrupt vectors");

IO_APIC_VECTOR(irq) = current_vector;
return current_vector;
@@ -1090,8 +1090,8 @@
else
irq_desc[irq].handler = &ioapic_edge_irq_type;

- set_intr_gate(vector, interrupt[irq]);
-
+ set_intr_gate_all(vector, interrupt[irq]);
+
if (!apic && (irq < 16))
disable_8259A_irq(irq);
}
@@ -1940,8 +1940,8 @@
*/
disable_8259A_irq(0);
vector = assign_irq_vector(0);
- set_intr_gate(vector, interrupt[0]);
-
+ set_intr_gate_all(vector, interrupt[0]);
+
/*
* Subtle, code in do_timer_interrupt() expects an AEOI
* mode for the 8259A whenever interrupts are routed
@@ -2228,7 +2228,7 @@

irq_desc[irq].handler = &ioapic_level_irq_type;

- set_intr_gate(entry.vector, interrupt[irq]);
+ set_intr_gate_all(entry.vector, interrupt[irq]);

if (!ioapic && (irq < 16))
disable_8259A_irq(irq);
Index: linux-2.5.62-numaq/arch/i386/kernel/irq.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.62/arch/i386/kernel/irq.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 irq.c
--- linux-2.5.62-numaq/arch/i386/kernel/irq.c 18 Feb 2003 00:16:06 -0000 1.1.1.1
+++ linux-2.5.62-numaq/arch/i386/kernel/irq.c 24 Feb 2003 01:47:45 -0000
@@ -65,7 +65,7 @@
/*
* Controller mappings for all interrupt sources:
*/
-irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
{ [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}};

static void register_irq_proc (unsigned int irq);
Index: linux-2.5.62-numaq/arch/i386/kernel/smpboot.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.62/arch/i386/kernel/smpboot.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 smpboot.c
--- linux-2.5.62-numaq/arch/i386/kernel/smpboot.c 18 Feb 2003 00:16:06 -0000 1.1.1.1
+++ linux-2.5.62-numaq/arch/i386/kernel/smpboot.c 24 Feb 2003 04:38:06 -0000
@@ -1163,22 +1165,22 @@
* IRQ0 must be given a fixed assignment and initialized,
* because it's used before the IO-APIC is set up.
*/
- set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
+ set_intr_gate_all(FIRST_DEVICE_VECTOR, interrupt[0]);

/*
* The reschedule interrupt is a CPU-to-CPU reschedule-helper
* IPI, driven by wakeup.
*/
- set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
+ set_intr_gate_all(RESCHEDULE_VECTOR, reschedule_interrupt);

/* IPI for invalidation */
- set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
+ set_intr_gate_all(INVALIDATE_TLB_VECTOR, invalidate_interrupt);

/* IPI for generic function call */
- set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
+ set_intr_gate_all(CALL_FUNCTION_VECTOR, call_function_interrupt);

/* thermal monitor LVT interrupt */
#ifdef CONFIG_X86_MCE_P4THERMAL
- set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
+ set_intr_gate_all(THERMAL_APIC_VECTOR, thermal_interrupt);
#endif
}
Index: linux-2.5.62-numaq/arch/i386/kernel/traps.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.62/arch/i386/kernel/traps.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 traps.c
--- linux-2.5.62-numaq/arch/i386/kernel/traps.c 18 Feb 2003 00:16:06 -0000 1.1.1.1
+++ linux-2.5.62-numaq/arch/i386/kernel/traps.c 24 Feb 2003 05:57:37 -0000
@@ -63,7 +63,9 @@
* F0 0F bug workaround.. We have a special link segment
* for this.
*/
-struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
+
+struct desc_struct cpu_idt_table[NR_CPUS][256] __attribute__((__section__(".data.idt"))) =
+ {[0 ... NR_CPUS-1] = { {0, 0}, }};

asmlinkage void divide_error(void);
asmlinkage void debug(void);
@@ -764,14 +766,16 @@
#ifdef CONFIG_X86_F00F_BUG
void __init trap_init_f00f_bug(void)
{
- __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
+ int cpu = smp_processor_id();
+
+ __set_fixmap(FIX_F00F_IDT, __pa(&cpu_idt_table[cpu]), PAGE_KERNEL_RO);

/*
* Update the IDT descriptor and reload the IDT so that
* it uses the read-only mapped virtual address.
*/
- idt_descr.address = fix_to_virt(FIX_F00F_IDT);
- __asm__ __volatile__("lidt %0": "=m" (idt_descr));
+ cpu_idt_descr[cpu].address = fix_to_virt(FIX_F00F_IDT);
+ __asm__ __volatile__("lidt %0": "=m" (cpu_idt_descr[cpu]));
}
#endif

@@ -790,24 +794,34 @@


/*
- * This needs to use 'idt_table' rather than 'idt', and
+ * This needs to use 'cpu_idt_table' rather than 'idt', and
* thus use the _nonmapped_ version of the IDT, as the
* Pentium F0 0F bugfix can have resulted in the mapped
* IDT being write-protected.
*/
-void set_intr_gate(unsigned int n, void *addr)
+void set_intr_gate(unsigned int cpu, unsigned int n, void *addr)
{
- _set_gate(idt_table+n,14,0,addr);
+ _set_gate(&cpu_idt_table[cpu][n],14,0,addr);
}

-static void __init set_trap_gate(unsigned int n, void *addr)
+void set_intr_gate_all(unsigned int n, void *addr)
{
- _set_gate(idt_table+n,15,0,addr);
+ int cpu;
+ for (cpu = 0; cpu < NR_CPUS; cpu++)
+ set_intr_gate(cpu, n, addr);
}

-static void __init set_system_gate(unsigned int n, void *addr)
+/* during boot we will copy the initial IDT from the boot processor,
+ * so only populate the BSP from here
+ */
+static void __init set_trap_gate(unsigned int cpu, unsigned int n, void *addr)
{
- _set_gate(idt_table+n,15,3,addr);
+ _set_gate(&cpu_idt_table[cpu][n],15,0,addr);
+}
+
+static void __init set_system_gate(unsigned int cpu, unsigned int n, void *addr)
+{
+ _set_gate(&cpu_idt_table[cpu][n],15,3,addr);
}

static void __init set_call_gate(void *a, void *addr)
@@ -834,32 +848,30 @@
#ifdef CONFIG_X86_LOCAL_APIC
init_apic_mappings();
#endif
-
- set_trap_gate(0,&divide_error);
- set_intr_gate(1,&debug);
- set_intr_gate(2,&nmi);
- set_system_gate(3,&int3); /* int3-5 can be called from all */
- set_system_gate(4,&overflow);
- set_system_gate(5,&bounds);
- set_trap_gate(6,&invalid_op);
- set_trap_gate(7,&device_not_available);
- set_trap_gate(8,&double_fault);
- set_trap_gate(9,&coprocessor_segment_overrun);
- set_trap_gate(10,&invalid_TSS);
- set_trap_gate(11,&segment_not_present);
- set_trap_gate(12,&stack_segment);
- set_trap_gate(13,&general_protection);
- set_intr_gate(14,&page_fault);
- set_trap_gate(15,&spurious_interrupt_bug);
- set_trap_gate(16,&coprocessor_error);
- set_trap_gate(17,&alignment_check);
+ set_trap_gate(0,0,&divide_error);
+ set_intr_gate(0,1,&debug);
+ set_intr_gate(0,2,&nmi);
+ set_system_gate(0,3,&int3); /* int3-5 can be called from all */
+ set_system_gate(0,4,&overflow);
+ set_system_gate(0,5,&bounds);
+ set_trap_gate(0,6,&invalid_op);
+ set_trap_gate(0,7,&device_not_available);
+ set_trap_gate(0,8,&double_fault);
+ set_trap_gate(0,9,&coprocessor_segment_overrun);
+ set_trap_gate(0,10,&invalid_TSS);
+ set_trap_gate(0,11,&segment_not_present);
+ set_trap_gate(0,12,&stack_segment);
+ set_trap_gate(0,13,&general_protection);
+ set_intr_gate(0,14,&page_fault);
+ set_trap_gate(0,15,&spurious_interrupt_bug);
+ set_trap_gate(0,16,&coprocessor_error);
+ set_trap_gate(0,17,&alignment_check);
#ifdef CONFIG_X86_MCE
- set_trap_gate(18,&machine_check);
+ set_trap_gate(0,18,&machine_check);
#endif
- set_trap_gate(19,&simd_coprocessor_error);
-
- set_system_gate(SYSCALL_VECTOR,&system_call);
-
+ set_trap_gate(0,19,&simd_coprocessor_error);
+ set_system_gate(0,SYSCALL_VECTOR,&system_call);
+
/*
* default LDT is a single-entry callgate to lcall7 for iBCS
* and a callgate to lcall27 for Solaris/x86 binaries
Index: linux-2.5.62-numaq/arch/i386/kernel/cpu/common.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.62/arch/i386/kernel/cpu/common.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 common.c
--- linux-2.5.62-numaq/arch/i386/kernel/cpu/common.c 18 Feb 2003 00:16:06 -0000 1.1.1.1
+++ linux-2.5.62-numaq/arch/i386/kernel/cpu/common.c 24 Feb 2003 05:58:50 -0000
@@ -454,13 +454,17 @@
}

/*
- * Initialize the per-CPU GDT with the boot GDT,
- * and set up the GDT descriptor:
+ * Initialize the per-CPU GDT and IDT with the boot equivalents,
+ * and set up the descriptors:
*/
if (cpu) {
memcpy(cpu_gdt_table[cpu], cpu_gdt_table[0], GDT_SIZE);
cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu];
+
+ memcpy(cpu_idt_table[cpu], cpu_idt_table[0], IDT_SIZE);
+ cpu_idt_descr[cpu].size = IDT_SIZE - 1;
+ cpu_idt_descr[cpu].address = (unsigned long)cpu_idt_table[cpu];
}
/*
* Set up the per-thread TLS descriptor cache:
@@ -468,7 +472,7 @@
memcpy(thread->tls_array, cpu_gdt_table[cpu], GDT_ENTRY_TLS_ENTRIES * 8);

__asm__ __volatile__("lgdt %0": "=m" (cpu_gdt_descr[cpu]));
- __asm__ __volatile__("lidt %0": "=m" (idt_descr));
+ __asm__ __volatile__("lidt %0": "=m" (cpu_idt_descr[cpu]));

/*
* Delete NT
Index: linux-2.5.62-numaq/arch/i386/mm/fault.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.62/arch/i386/mm/fault.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 fault.c
--- linux-2.5.62-numaq/arch/i386/mm/fault.c 18 Feb 2003 00:16:07 -0000 1.1.1.1
+++ linux-2.5.62-numaq/arch/i386/mm/fault.c 24 Feb 2003 04:01:36 -0000
@@ -299,7 +299,7 @@
if (boot_cpu_data.f00f_bug) {
unsigned long nr;

- nr = (address - idt_descr.address) >> 3;
+ nr = (address - cpu_idt_descr[smp_processor_id()].address) >> 3;

if (nr == 6) {
do_invalid_op(regs, 0);
Index: linux-2.5.62-numaq/include/asm-i386/desc.h
===================================================================
RCS file: /build/cvsroot/linux-2.5.62/include/asm-i386/desc.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 desc.h
--- linux-2.5.62-numaq/include/asm-i386/desc.h 18 Feb 2003 00:15:59 -0000 1.1.1.1
+++ linux-2.5.62-numaq/include/asm-i386/desc.h 24 Feb 2003 04:30:40 -0000
@@ -12,6 +12,7 @@
#include <asm/mmu.h>

extern struct desc_struct cpu_gdt_table[NR_CPUS][GDT_ENTRIES];
+extern struct desc_struct cpu_idt_table[NR_CPUS][256];

struct Xgt_desc_struct {
unsigned short size;
@@ -19,7 +20,8 @@
unsigned short pad;
} __attribute__ ((packed));

-extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
+#define IDT_SIZE (256*8)
+extern struct Xgt_desc_struct cpu_idt_descr[NR_CPUS], cpu_gdt_descr[NR_CPUS];

#define load_TR_desc() __asm__ __volatile__("ltr %%ax"::"a" (GDT_ENTRY_TSS*8))
#define load_LDT_desc() __asm__ __volatile__("lldt %%ax"::"a" (GDT_ENTRY_LDT*8))
@@ -29,7 +31,8 @@
* something other than this.
*/
extern struct desc_struct default_ldt[];
-extern void set_intr_gate(unsigned int irq, void * addr);
+extern void set_intr_gate(unsigned int cpu, unsigned int irq, void * addr);
+extern void set_intr_gate_all(unsigned int n, void *addr);

#define _set_tssldt_desc(n,addr,limit,type) \
__asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-03-22 13:33    [W:0.024 / U:3.080 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site