bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/4] i386: Add AP variants of descriptor tables


From: Damien Zammit
Subject: [PATCH 1/4] i386: Add AP variants of descriptor tables
Date: Fri, 11 Nov 2022 23:21:15 +0000

---
 i386/i386/apic.c        |  6 ++++++
 i386/i386/gdt.c         | 47 ++++++++++++++++++++++++++++++-----------
 i386/i386/gdt.h         |  1 +
 i386/i386/i386asm.sym   |  1 +
 i386/i386/idt-gen.h     |  4 ++--
 i386/i386/idt.c         | 25 ++++++++++++++++------
 i386/i386/ktss.c        | 30 +++++++++++++++++++-------
 i386/i386/ktss.h        |  1 +
 i386/i386/ldt.c         | 31 ++++++++++++++++++++-------
 i386/i386/ldt.h         |  9 ++++----
 i386/i386/locore.S      |  4 ++++
 i386/i386at/idt.h       |  4 ++++
 i386/i386at/int_init.c  | 39 +++++++++++++++++++++++++---------
 i386/i386at/int_init.h  |  1 +
 i386/i386at/interrupt.S | 16 ++++++++++++++
 i386/i386at/ioapic.c    |  6 ------
 16 files changed, 169 insertions(+), 56 deletions(-)

diff --git a/i386/i386/apic.c b/i386/i386/apic.c
index 2e0c1776..d30084e2 100644
--- a/i386/i386/apic.c
+++ b/i386/i386/apic.c
@@ -234,3 +234,9 @@ void apic_print_info(void)
         }
     }
 }
+
+void
+lapic_eoi(void)
+{
+    lapic->eoi.r = 0;
+}
diff --git a/i386/i386/gdt.c b/i386/i386/gdt.c
index fb18360e..ddda603b 100644
--- a/i386/i386/gdt.c
+++ b/i386/i386/gdt.c
@@ -39,6 +39,7 @@
 #include "vm_param.h"
 #include "seg.h"
 #include "gdt.h"
+#include "mp_desc.h"

 #ifdef MACH_PV_DESCRIPTORS
 /* It is actually defined in xen_boothdr.S */
@@ -46,28 +47,28 @@ extern
 #endif /* MACH_PV_DESCRIPTORS */
 struct real_descriptor gdt[GDTSZ];

-void
-gdt_init(void)
+static void
+gdt_fill(struct real_descriptor *mygdt)
 {
        /* Initialize the kernel code and data segment descriptors.  */
 #ifdef __x86_64__
        assert(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS == 0);
-       fill_gdt_descriptor(KERNEL_CS, 0, 0, ACC_PL_K|ACC_CODE_R, SZ_64);
-       fill_gdt_descriptor(KERNEL_DS, 0, 0, ACC_PL_K|ACC_DATA_W, SZ_64);
+       _fill_gdt_descriptor(mygdt, KERNEL_CS, 0, 0, ACC_PL_K|ACC_CODE_R, 
SZ_64);
+       _fill_gdt_descriptor(mygdt, KERNEL_DS, 0, 0, ACC_PL_K|ACC_DATA_W, 
SZ_64);
 #ifndef        MACH_PV_DESCRIPTORS
-       fill_gdt_descriptor(LINEAR_DS, 0, 0, ACC_PL_K|ACC_DATA_W, SZ_64);
+       _fill_gdt_descriptor(mygdt, LINEAR_DS, 0, 0, ACC_PL_K|ACC_DATA_W, 
SZ_64);
 #endif /* MACH_PV_DESCRIPTORS */
 #else
-       fill_gdt_descriptor(KERNEL_CS,
+       _fill_gdt_descriptor(mygdt, KERNEL_CS,
                            LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS,
                            LINEAR_MAX_KERNEL_ADDRESS - 
(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) - 1,
                            ACC_PL_K|ACC_CODE_R, SZ_32);
-       fill_gdt_descriptor(KERNEL_DS,
+       _fill_gdt_descriptor(mygdt, KERNEL_DS,
                            LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS,
                            LINEAR_MAX_KERNEL_ADDRESS - 
(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) - 1,
                            ACC_PL_K|ACC_DATA_W, SZ_32);
 #ifndef        MACH_PV_DESCRIPTORS
-       fill_gdt_descriptor(LINEAR_DS,
+       _fill_gdt_descriptor(mygdt, LINEAR_DS,
                            0,
                            0xffffffff,
                            ACC_PL_K|ACC_DATA_W, SZ_32);
@@ -75,8 +76,8 @@ gdt_init(void)
 #endif

 #ifdef MACH_PV_DESCRIPTORS
-       unsigned long frame = kv_to_mfn(gdt);
-       pmap_set_page_readonly(gdt);
+       unsigned long frame = kv_to_mfn(mygdt);
+       pmap_set_page_readonly(mygdt);
        if (hyp_set_gdt(kv_to_la(&frame), GDTSZ))
                panic("couldn't set gdt\n");
 #endif
@@ -94,12 +95,16 @@ gdt_init(void)
        {
                struct pseudo_descriptor pdesc;

-               pdesc.limit = sizeof(gdt)-1;
-               pdesc.linear_base = kvtolin(&gdt);
+               pdesc.limit = (GDTSZ * sizeof(struct real_descriptor))-1;
+               pdesc.linear_base = kvtolin(mygdt);
                lgdt(&pdesc);
        }
 #endif /* MACH_PV_DESCRIPTORS */
+}

+static void
+reload_segs(void)
+{
        /* Reload all the segment registers from the new GDT.
           We must load ds and es with 0 before loading them with KERNEL_DS
           because some processors will "optimize out" the loads
@@ -117,6 +122,15 @@ gdt_init(void)
                     "movw      %w1,%%ss\n"
                     : : "i" (KERNEL_CS), "r" (KERNEL_DS), "r" (0));
 #endif
+}
+
+void
+gdt_init(void)
+{
+       gdt_fill(gdt);
+
+       reload_segs();
+
 #ifdef MACH_PV_PAGETABLES
 #if VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS
        /* things now get shifted */
@@ -128,3 +142,12 @@ gdt_init(void)
 #endif /* MACH_PV_PAGETABLES */
 }

+#if NCPUS > 1
+void
+ap_gdt_init(int cpu)
+{
+       gdt_fill(mp_gdt[cpu]);
+
+       reload_segs();
+}
+#endif
diff --git a/i386/i386/gdt.h b/i386/i386/gdt.h
index 9879ad3e..5def73cb 100644
--- a/i386/i386/gdt.h
+++ b/i386/i386/gdt.h
@@ -115,5 +115,6 @@ extern struct real_descriptor gdt[GDTSZ];
 #endif

 extern void gdt_init(void);
+extern void ap_gdt_init(int cpu);

 #endif /* _I386_GDT_ */
diff --git a/i386/i386/i386asm.sym b/i386/i386/i386asm.sym
index 9f4ebe55..85658b30 100644
--- a/i386/i386/i386asm.sym
+++ b/i386/i386/i386asm.sym
@@ -47,6 +47,7 @@
 #include <i386/mp_desc.h>
 #include <i386/xen.h>

+expr   CALL_SINGLE_FUNCTION_BASE

 offset thread                  th      pcb
 offset thread                  th      task
diff --git a/i386/i386/idt-gen.h b/i386/i386/idt-gen.h
index f86afb41..daa6aaf2 100644
--- a/i386/i386/idt-gen.h
+++ b/i386/i386/idt-gen.h
@@ -41,7 +41,7 @@
 extern struct real_gate idt[IDTSZ];

 /* Fill a gate in the IDT.  */
-#define fill_idt_gate(int_num, entry, selector, access, dword_count) \
-       fill_gate(&idt[int_num], entry, selector, access, dword_count)
+#define fill_idt_gate(_idt, int_num, entry, selector, access, dword_count) \
+       fill_gate(&_idt[int_num], entry, selector, access, dword_count)

 #endif /* _I386_IDT_ */
diff --git a/i386/i386/idt.c b/i386/i386/idt.c
index c6a778f1..06ff6dbc 100644
--- a/i386/i386/idt.c
+++ b/i386/i386/idt.c
@@ -25,6 +25,7 @@
 #include <i386/seg.h>
 #include <i386at/idt.h>
 #include <i386/gdt.h>
+#include <i386/mp_desc.h>

 struct real_gate idt[IDTSZ];

@@ -36,7 +37,8 @@ struct idt_init_entry
 };
 extern struct idt_init_entry idt_inittab[];

-void idt_init(void)
+static void
+idt_fill(struct real_gate *myidt)
 {
 #ifdef MACH_PV_DESCRIPTORS
        if (hyp_set_trap_table(kvtolin(idt_inittab)))
@@ -47,18 +49,29 @@ void idt_init(void)
        /* Initialize the exception vectors from the idt_inittab.  */
        while (iie->entrypoint)
        {
-               fill_idt_gate(iie->vector, iie->entrypoint, KERNEL_CS, 
iie->type, 0);
+               fill_idt_gate(myidt, iie->vector, iie->entrypoint, KERNEL_CS, 
iie->type, 0);
                iie++;
        }
+#endif /* MACH_PV_DESCRIPTORS */

-       /* Load the IDT pointer into the processor.  */
+       /* Load the IDT pointer into the processor */
        {
                struct pseudo_descriptor pdesc;

-               pdesc.limit = sizeof(idt)-1;
-               pdesc.linear_base = kvtolin(&idt);
+               pdesc.limit = (IDTSZ * sizeof(struct real_gate))-1;
+               pdesc.linear_base = kvtolin(myidt);
                lidt(&pdesc);
        }
-#endif /* MACH_PV_DESCRIPTORS */
 }

+void idt_init(void)
+{
+       idt_fill(idt);
+}
+
+#if NCPUS > 1
+void ap_idt_init(int cpu)
+{
+       idt_fill(mp_desc_table[cpu]->idt);
+}
+#endif
diff --git a/i386/i386/ktss.c b/i386/i386/ktss.c
index 0d21d3eb..5cc260fc 100644
--- a/i386/i386/ktss.c
+++ b/i386/i386/ktss.c
@@ -35,12 +35,13 @@
 #include "seg.h"
 #include "gdt.h"
 #include "ktss.h"
+#include "mp_desc.h"

 /* A kernel TSS with a complete I/O bitmap.  */
 struct task_tss ktss;

 void
-ktss_init(void)
+ktss_fill(struct task_tss *myktss, struct real_descriptor *mygdt)
 {
        /* XXX temporary exception stack */
        static int exception_stack[1024];
@@ -52,24 +53,37 @@ ktss_init(void)
                panic("couldn't register exception stack\n");
 #else  /* MACH_RING1 */
        /* Initialize the master TSS descriptor.  */
-       fill_gdt_sys_descriptor(KERNEL_TSS,
-                               kvtolin(&ktss), sizeof(struct task_tss) - 1,
+       _fill_gdt_sys_descriptor(mygdt, KERNEL_TSS,
+                               kvtolin(myktss), sizeof(struct task_tss) - 1,
                                ACC_PL_K|ACC_TSS, 0);

        /* Initialize the master TSS.  */
 #ifdef __x86_64__
-       ktss.tss.rsp0 = (unsigned long)(exception_stack+1024);
+       myktss->tss.rsp0 = (unsigned long)(exception_stack+1024);
 #else /* ! __x86_64__ */
-       ktss.tss.ss0 = KERNEL_DS;
-       ktss.tss.esp0 = (unsigned long)(exception_stack+1024);
+       myktss->tss.ss0 = KERNEL_DS;
+       myktss->tss.esp0 = (unsigned long)(exception_stack+1024);
 #endif /* __x86_64__ */

-       ktss.tss.io_bit_map_offset = IOPB_INVAL;
+       myktss->tss.io_bit_map_offset = IOPB_INVAL;
        /* Set the last byte in the I/O bitmap to all 1's.  */
-       ktss.barrier = 0xff;
+       myktss->barrier = 0xff;

        /* Load the TSS.  */
        ltr(KERNEL_TSS);
 #endif /* MACH_RING1 */
 }

+void
+ktss_init(void)
+{
+       ktss_fill(&ktss, gdt);
+}
+
+#if NCPUS > 1
+void
+ap_ktss_init(int cpu)
+{
+       ktss_fill(&mp_desc_table[cpu]->ktss, mp_gdt[cpu]);
+}
+#endif
diff --git a/i386/i386/ktss.h b/i386/i386/ktss.h
index 304a877a..171332da 100644
--- a/i386/i386/ktss.h
+++ b/i386/i386/ktss.h
@@ -28,5 +28,6 @@
 extern struct task_tss ktss;

 extern void ktss_init(void);
+extern void ap_ktss_init(int cpu);

 #endif /* _I386_KTSS_ */
diff --git a/i386/i386/ldt.c b/i386/i386/ldt.c
index 261df93a..3f9ac8ff 100644
--- a/i386/i386/ldt.c
+++ b/i386/i386/ldt.c
@@ -37,6 +37,7 @@
 #include "gdt.h"
 #include "ldt.h"
 #include "locore.h"
+#include "mp_desc.h"

 #ifdef MACH_PV_DESCRIPTORS
 /* It is actually defined in xen_boothdr.S */
@@ -45,37 +46,51 @@ extern
 struct real_descriptor ldt[LDTSZ];

 void
-ldt_init(void)
+ldt_fill(struct real_descriptor *myldt, struct real_descriptor *mygdt)
 {
 #ifdef MACH_PV_DESCRIPTORS
 #ifdef MACH_PV_PAGETABLES
-       pmap_set_page_readwrite(ldt);
+       pmap_set_page_readwrite(myldt);
 #endif /* MACH_PV_PAGETABLES */
 #else  /* MACH_PV_DESCRIPTORS */
        /* Initialize the master LDT descriptor in the GDT.  */
-       fill_gdt_sys_descriptor(KERNEL_LDT,
-                               kvtolin(&ldt), sizeof(ldt)-1,
+       _fill_gdt_sys_descriptor(mygdt, KERNEL_LDT,
+                               kvtolin(myldt), (LDTSZ * sizeof(struct 
real_descriptor))-1,
                                ACC_PL_K|ACC_LDT, 0);
 #endif /* MACH_PV_DESCRIPTORS */

        /* Initialize the 32bit LDT descriptors.  */
-       fill_ldt_gate(USER_SCALL,
+       fill_ldt_gate(myldt, USER_SCALL,
                      (vm_offset_t)&syscall, KERNEL_CS,
                      ACC_PL_U|ACC_CALL_GATE, 0);
-       fill_ldt_descriptor(USER_CS,
+       fill_ldt_descriptor(myldt, USER_CS,
                            VM_MIN_ADDRESS,
                            VM_MAX_ADDRESS-VM_MIN_ADDRESS-4096,
                            /* XXX LINEAR_... */
                            ACC_PL_U|ACC_CODE_R, SZ_32);
-       fill_ldt_descriptor(USER_DS,
+       fill_ldt_descriptor(myldt, USER_DS,
                            VM_MIN_ADDRESS,
                            VM_MAX_ADDRESS-VM_MIN_ADDRESS-4096,
                            ACC_PL_U|ACC_DATA_W, SZ_32);

        /* Activate the LDT.  */
 #ifdef MACH_PV_DESCRIPTORS
-       hyp_set_ldt(&ldt, LDTSZ);
+       hyp_set_ldt(myldt, LDTSZ);
 #else  /* MACH_PV_DESCRIPTORS */
        lldt(KERNEL_LDT);
 #endif /* MACH_PV_DESCRIPTORS */
 }
+
+void
+ldt_init(void)
+{
+       ldt_fill(ldt, gdt);
+}
+
+#if NCPUS > 1
+void
+ap_ldt_init(int cpu)
+{
+       ldt_fill(mp_desc_table[cpu]->ldt, mp_gdt[cpu]);
+}
+#endif
diff --git a/i386/i386/ldt.h b/i386/i386/ldt.h
index 1f0d7014..b15f11a5 100644
--- a/i386/i386/ldt.h
+++ b/i386/i386/ldt.h
@@ -57,14 +57,15 @@
 extern struct real_descriptor ldt[LDTSZ];

 /* Fill a 32bit segment descriptor in the LDT.  */
-#define fill_ldt_descriptor(selector, base, limit, access, sizebits) \
-       fill_descriptor(&ldt[sel_idx(selector)], base, limit, access, sizebits)
+#define fill_ldt_descriptor(_ldt, selector, base, limit, access, sizebits) \
+       fill_descriptor(&_ldt[sel_idx(selector)], base, limit, access, sizebits)

-#define fill_ldt_gate(selector, offset, dest_selector, access, word_count) \
-       fill_gate((struct real_gate*)&ldt[sel_idx(selector)], \
+#define fill_ldt_gate(_ldt, selector, offset, dest_selector, access, 
word_count) \
+       fill_gate((struct real_gate*)&_ldt[sel_idx(selector)], \
                  offset, dest_selector, access, word_count)

 void ldt_init(void);
+void ap_ldt_init(int cpu);

 #endif /* !__ASSEMBLER__ */

diff --git a/i386/i386/locore.S b/i386/i386/locore.S
index 162bb13a..b5122613 100644
--- a/i386/i386/locore.S
+++ b/i386/i386/locore.S
@@ -649,6 +649,10 @@ INTERRUPT(20)
 INTERRUPT(21)
 INTERRUPT(22)
 INTERRUPT(23)
+#endif
+/* Invalidate TLB IPI to call pmap_update_interrupt() on a specific cpu */
+INTERRUPT(CALL_SINGLE_FUNCTION_BASE)
+#ifdef APIC
 /* Spurious interrupt, set irq number to vect number */
 INTERRUPT(255)
 #endif
diff --git a/i386/i386at/idt.h b/i386/i386at/idt.h
index ac065aef..f080bb12 100644
--- a/i386/i386at/idt.h
+++ b/i386/i386at/idt.h
@@ -37,10 +37,14 @@
 /* IOAPIC spurious interrupt vector set to 0xff */
 #define IOAPIC_SPURIOUS_BASE 0xff

+/* Currently for TLB shootdowns */
+#define CALL_SINGLE_FUNCTION_BASE 0xfb
+
 #include <i386/idt-gen.h>

 #ifndef __ASSEMBLER__
 extern void idt_init (void);
+extern void ap_idt_init (int cpu);
 #endif /* __ASSEMBLER__ */

 #endif /* _I386AT_IDT_ */
diff --git a/i386/i386at/int_init.c b/i386/i386at/int_init.c
index 6da627dd..da552106 100644
--- a/i386/i386at/int_init.c
+++ b/i386/i386at/int_init.c
@@ -22,29 +22,48 @@
  */

 #include <i386at/idt.h>
-#include <i386/gdt.h>
+#include <i386/mp_desc.h>
+#include <i386/i386asm.h>

 /* defined in locore.S */
 extern vm_offset_t int_entry_table[];

-void int_init(void)
+void
+int_fill(struct real_gate *myidt)
 {
        int i;
 #ifndef APIC
-       for (i = 0; i < 16; i++) {
-               fill_idt_gate(PIC_INT_BASE + i,
+       int base = PIC_INT_BASE;
+       int nirq = 16;
+#else
+       int base = IOAPIC_INT_BASE;
+       int nirq = 24;
+#endif
+
+       for (i = 0; i < nirq; i++) {
+               fill_idt_gate(myidt, base + i,
                              int_entry_table[i], KERNEL_CS,
                              ACC_PL_K|ACC_INTR_GATE, 0);
        }
-#else
-       for (i = 0; i < 24; i++) {
-               fill_idt_gate(IOAPIC_INT_BASE + i,
+       fill_idt_gate(myidt, CALL_SINGLE_FUNCTION_BASE,
                              int_entry_table[i], KERNEL_CS,
                              ACC_PL_K|ACC_INTR_GATE, 0);
-       }
-       fill_idt_gate(IOAPIC_SPURIOUS_BASE,
-                             int_entry_table[24], KERNEL_CS,
+#ifdef APIC
+       fill_idt_gate(myidt, IOAPIC_SPURIOUS_BASE,
+                             int_entry_table[25], KERNEL_CS,
                              ACC_PL_K|ACC_INTR_GATE, 0);
 #endif
 }

+void
+int_init(void)
+{
+       int_fill(idt);
+}
+
+#if NCPUS > 1
+void ap_int_init(int cpu)
+{
+       int_fill(mp_desc_table[cpu]->idt);
+}
+#endif
diff --git a/i386/i386at/int_init.h b/i386/i386at/int_init.h
index f9b03b74..3c11ebce 100644
--- a/i386/i386at/int_init.h
+++ b/i386/i386at/int_init.h
@@ -29,6 +29,7 @@

 #ifndef __ASSEMBLER__
 extern void int_init (void);
+extern void ap_int_init (int cpu);
 #endif /* __ASSEMBLER__ */

 #endif /* _INT_INIT_H_ */
diff --git a/i386/i386at/interrupt.S b/i386/i386at/interrupt.S
index 7480fba9..9eccf022 100644
--- a/i386/i386at/interrupt.S
+++ b/i386/i386at/interrupt.S
@@ -41,6 +41,9 @@ ENTRY(interrupt)
        cmpl    $255,%eax               /* was this a spurious intr? */
        je      _no_eoi                 /* if so, just return */
 #endif
+       cmpl    $251,%eax               /* was this a SMP call single function 
request? */
+       je      _call_single
+
        subl    $28,%esp                /* Two local variables + 5 parameters */
        movl    %eax,S_IRQ              /* save irq number */
        call    spl7                    /* set ipl */
@@ -118,4 +121,17 @@ _isa_eoi:
        addl    $28,%esp                /* pop local variables */
 _no_eoi:
        ret
+_call_single:
+       subl    $8,%esp                 /* One param */
+       movl    %eax,S_ARG0             /* save irq number */
+       call    spl7                    /* set ipl */
+       movl    %eax,S_ARG1             /* save previous ipl */
+       call    EXT(pmap_update_interrupt) /* TODO: Allow other functions */
+       movl    S_ARG1,%eax             /* restore previous ipl */
+       call    splx_cli                /* restore previous ipl */
+       cli
+       movl    S_ARG0,%eax             /* restore irq number */
+       call    EXT(lapic_eoi)          /* lapic EOI */
+       addl    $8,%esp
+       ret
 END(interrupt)
diff --git a/i386/i386at/ioapic.c b/i386/i386at/ioapic.c
index 18a9bec6..7b30c5c0 100644
--- a/i386/i386at/ioapic.c
+++ b/i386/i386at/ioapic.c
@@ -233,12 +233,6 @@ ioapic_toggle(int pin, int mask)
     ioapic_toggle_entry(apic, pin, mask);
 }

-void
-lapic_eoi(void)
-{
-    lapic->eoi.r = 0;
-}
-
 void
 ioapic_irq_eoi(int pin)
 {
--
2.34.1





reply via email to

[Prev in Thread] Current Thread [Next in Thread]