diff options
author | Damien Zammit <damien@zamaudio.com> | 2023-01-29 23:45:38 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2023-01-29 23:49:04 +0100 |
commit | fc0d49a3eda8b89497d1f2908b29b5476019a818 (patch) | |
tree | 51a607c61cbbc1d9b9c582c3a0afcf9dfdfb4e63 | |
parent | 6ebd651d6f6244315a84b8355d801d118869f722 (diff) | |
download | gnumach-fc0d49a3eda8b89497d1f2908b29b5476019a818.tar.gz gnumach-fc0d49a3eda8b89497d1f2908b29b5476019a818.tar.bz2 gnumach-fc0d49a3eda8b89497d1f2908b29b5476019a818.zip |
i386: Add AP variants of descriptor tables
-rw-r--r-- | i386/i386/apic.c | 6 | ||||
-rw-r--r-- | i386/i386/gdt.c | 47 | ||||
-rw-r--r-- | i386/i386/gdt.h | 1 | ||||
-rw-r--r-- | i386/i386/i386asm.sym | 1 | ||||
-rw-r--r-- | i386/i386/idt-gen.h | 4 | ||||
-rw-r--r-- | i386/i386/idt.c | 21 | ||||
-rw-r--r-- | i386/i386/ktss.c | 31 | ||||
-rw-r--r-- | i386/i386/ktss.h | 1 | ||||
-rw-r--r-- | i386/i386/ldt.c | 31 | ||||
-rw-r--r-- | i386/i386/ldt.h | 9 | ||||
-rw-r--r-- | i386/i386/locore.S | 4 | ||||
-rw-r--r-- | i386/i386/mp_desc.h | 2 | ||||
-rw-r--r-- | i386/i386at/idt.h | 4 | ||||
-rw-r--r-- | i386/i386at/int_init.c | 41 | ||||
-rw-r--r-- | i386/i386at/int_init.h | 1 | ||||
-rw-r--r-- | i386/i386at/interrupt.S | 9 | ||||
-rw-r--r-- | i386/i386at/ioapic.c | 6 |
17 files changed, 165 insertions, 54 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..cdfb9a88 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,7 +49,7 @@ 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++; } @@ -55,10 +57,21 @@ void idt_init(void) { 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..1d880167 100644 --- a/i386/i386/ktss.c +++ b/i386/i386/ktss.c @@ -35,14 +35,16 @@ #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 */ + /* FIXME: make it per-processor */ static int exception_stack[1024]; #ifdef MACH_RING1 @@ -52,24 +54,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 f50aca5d..ff78e80d 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/i386/mp_desc.h b/i386/i386/mp_desc.h index ebe1471d..ede8775f 100644 --- a/i386/i386/mp_desc.h +++ b/i386/i386/mp_desc.h @@ -27,6 +27,8 @@ #ifndef _I386_MP_DESC_H_ #define _I386_MP_DESC_H_ +#include <mach/kern_return.h> + #if MULTIPROCESSOR /* 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 3fed4197..964ce1bb 100644 --- a/i386/i386at/int_init.c +++ b/i386/i386at/int_init.c @@ -23,29 +23,50 @@ #include <i386at/idt.h> #include <i386at/int_init.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, + i++; +#ifdef APIC + fill_idt_gate(myidt, IOAPIC_SPURIOUS_BASE, + int_entry_table[i], KERNEL_CS, ACC_PL_K|ACC_INTR_GATE, 0); + i++; #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 16e0df10..9f1883ac 100644 --- a/i386/i386at/interrupt.S +++ b/i386/i386at/interrupt.S @@ -58,6 +58,9 @@ ENTRY(interrupt) movl %eax,12(%esp) /* address of interrupted registers as 4th arg */ movl S_IRQ,%eax /* copy irq number */ + cmpl $CALL_SINGLE_FUNCTION_BASE,%eax /* was this a SMP call single function request? */ + je _call_single + shll $2,%eax /* irq * 4 */ movl EXT(iunit)(%eax),%edx /* get device unit number */ movl %edx,(%esp) /* unit number as 1st arg */ @@ -117,4 +120,10 @@ _isa_eoi: addl $24,%esp /* pop local variables */ _no_eoi: ret + +_call_single: + call EXT(pmap_update_interrupt) /* TODO: Allow other functions */ + call EXT(lapic_eoi) /* lapic EOI */ + addl $24,%esp + ret END(interrupt) diff --git a/i386/i386at/ioapic.c b/i386/i386at/ioapic.c index 3373aa71..c5eb3536 100644 --- a/i386/i386at/ioapic.c +++ b/i386/i386at/ioapic.c @@ -234,12 +234,6 @@ ioapic_toggle(int pin, int mask) } void -lapic_eoi(void) -{ - lapic->eoi.r = 0; -} - -void ioapic_irq_eoi(int pin) { int apic = 0; |