bug-hurd
[Top][All Lists]
Advanced

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

Re: [PATCH 09/12 gnumach] i386: Refactor int stacks for SMP - shared tem


From: Almudena Garcia
Subject: Re: [PATCH 09/12 gnumach] i386: Refactor int stacks for SMP - shared temp pmap
Date: Tue, 31 Jan 2023 16:30:21 +0100

void
 start_other_cpus(void)
 {
-       int cpu;
-       for (cpu = 0; cpu < NCPUS; cpu++)
-               if (cpu != cpu_number())
-                       cpu_start(cpu);
-}
+       unsigned long flags;
+
+       cpu_intr_save(&flags);
+
+       int ncpus = smp_get_numcpus();

+       //Copy cpu initialization assembly routine
+       memcpy((void*)phystokv(AP_BOOT_ADDR), (void*) &apboot,
+              (uint32_t)&apbootend - (uint32_t)&apboot);
+
+#ifndef APIC
+       lapic_enable(); /* Enable lapic only once */
+#endif
+       unsigned cpu;
+       bspdone = 0;
+       for (cpu = 1; cpu < ncpus; cpu++) {
+               machine_slot[cpu].running = FALSE;
+
+               //Start cpu
+               printf("Starting AP %d\n", cpu);
+               cpu_start(cpu);
+       }
+       printf("BSP: Completed SMP init\n");
+       bspdone = 1;
+
+       for (cpu = 1; cpu < ncpus; cpu++) {
+               do {
+                       asm volatile ("pause" : : : "memory");
+               } while (machine_slot[cpu].running == FALSE);
+       }
+
+        cpu_intr_restore(flags);
+}

Raise all startup IPI at same time could be dangerous: all cpus try to access to same assembly routine in the same address, added to other problems.
I prefer don't startup a new AP until the current AP is enabled.


+    /* Turn paging on.
+     * TODO: Why does setting the WP bit here cause a crash?
+     */
+    set_cr0(get_cr0() | CR0_PG /* | CR0_WP */);
+    set_cr0(get_cr0() & ~(CR0_CD | CR0_NW));
+    if (CPU_HAS_FEATURE(CPU_FEATURE_PGE))
+        set_cr4(get_cr4() | CR4_PGE);

I prefer to put this code in a separated function, calling this after cpu_setup() is finished.
+    unsigned apic_id = (((ApicLocalUnit*)phystokv(lapic_addr))->apic_id.r >> 24) & 0xff;

Be careful, because this type of access to lapic only works before pagging is enabled, only works with segmentation.
Once pagging is enabled, you must be able to access to local_apic (and apic_id) directly through its pointer. Even, after this, probably you can get the apic_id calling to the proper function which I implemented in apic.c

El mar, 31 ene 2023 a las 10:39, Damien Zammit (<damien@zamaudio.com>) escribió:
Also-by: Almudena Garcia <liberamenso10000@gmail.com>
---
 i386/i386/cpu_number.h           |  15 +-
 i386/i386/cswitch.S              |   6 +-
 i386/i386/i386asm.sym            |   3 +
 i386/i386/locore.S               |   4 +-
 i386/i386/mp_desc.c              | 227 ++++++++++++++++++++++---------
 i386/i386/mp_desc.h              |   7 +-
 i386/i386at/boothdr.S            |  18 ++-
 i386/i386at/ioapic.c             |   4 +-
 i386/i386at/model_dep.c          | 101 +++-----------
 i386/i386at/model_dep.h          |   3 +-
 i386/intel/pmap.c                | 103 ++++++++++++--
 i386/intel/pmap.h                |   6 +
 linux/dev/arch/i386/kernel/irq.c |  13 +-
 linux/dev/init/main.c            |   2 +
 14 files changed, 322 insertions(+), 190 deletions(-)

diff --git a/i386/i386/cpu_number.h b/i386/i386/cpu_number.h
index a6dd47d6..46232459 100644
--- a/i386/i386/cpu_number.h
+++ b/i386/i386/cpu_number.h
@@ -32,6 +32,8 @@

 #if    NCPUS > 1

+#include "apic.h"
+
 /* More-specific code must define cpu_number() and CPU_NUMBER.  */
 #ifdef __i386__
 #define        CX(addr, reg)   addr(,reg,4)
@@ -45,11 +47,14 @@
 #endif
 #ifdef __x86_64__
 #define        CX(addr, reg)   addr(,reg,8)
+#warning Missing CPU_NUMBER() for 64 bit
+#define CPU_NUMBER(reg)
 #endif

-/* XXX For now */
-#define        CPU_NUMBER(reg) movl $0,reg
-#define cpu_number() 0
+#ifndef __ASSEMBLER__
+#include "kern/cpu_number.h"
+int cpu_number(void);
+#endif

 #else  /* NCPUS == 1 */

@@ -58,8 +63,4 @@

 #endif /* NCPUS == 1 */

-#ifndef __ASSEMBLER__
-#include "kern/cpu_number.h"
-#endif
-
 #endif /* _I386_CPU_NUMBER_H_ */
diff --git a/i386/i386/cswitch.S b/i386/i386/cswitch.S
index 718c8aac..ae941bdd 100644
--- a/i386/i386/cswitch.S
+++ b/i386/i386/cswitch.S
@@ -110,7 +110,7 @@ ENTRY(Thread_continue)
  */
 ENTRY(switch_to_shutdown_context)
        CPU_NUMBER(%edx)
-       movl    EXT(active_stacks)(,%edx,4),%ecx        /* get old kernel stack */
+       movl    CX(EXT(active_stacks),%edx),%ecx        /* get old kernel stack */
        movl    %ebx,KSS_EBX(%ecx)              /* save registers */
        movl    %ebp,KSS_EBP(%ecx)
        movl    %edi,KSS_EDI(%ecx)
@@ -124,8 +124,8 @@ ENTRY(switch_to_shutdown_context)
        movl    4(%esp),%ebx                    /* get routine to run next */
        movl    8(%esp),%esi                    /* get its argument */

-       movl    EXT(interrupt_stack)(,%edx,4),%ecx      /* point to its interrupt stack */
-       lea     INTSTACK_SIZE(%ecx),%esp        /* switch to it (top) */
+       movl    CX(EXT(int_stack_base),%edx),%ecx       /* point to its interrupt stack */
+       lea     -4+INTSTACK_SIZE(%ecx),%esp     /* switch to it (top) */

        pushl   %eax                            /* push thread */
        call    EXT(thread_dispatch)            /* reschedule thread */
diff --git a/i386/i386/i386asm.sym b/i386/i386/i386asm.sym
index 85658b30..8317db6c 100644
--- a/i386/i386/i386asm.sym
+++ b/i386/i386/i386asm.sym
@@ -45,10 +45,13 @@
 #include <i386/gdt.h>
 #include <i386/ldt.h>
 #include <i386/mp_desc.h>
+#include <i386/apic.h>
 #include <i386/xen.h>

 expr   CALL_SINGLE_FUNCTION_BASE

+offset ApicLocalUnit           lu      apic_id         APIC_ID
+
 offset thread                  th      pcb
 offset thread                  th      task
 offset thread                  th      recover
diff --git a/i386/i386/locore.S b/i386/i386/locore.S
index 5ac238f7..55add6e4 100644
--- a/i386/i386/locore.S
+++ b/i386/i386/locore.S
@@ -689,6 +689,7 @@ ENTRY(all_intrs)
        CPU_NUMBER(%edx)

        movl    CX(EXT(int_stack_top),%edx),%ecx
+
        xchgl   %ecx,%esp               /* switch to interrupt stack */

 #if    STAT_TIME
@@ -733,7 +734,8 @@ LEXT(return_to_iret)                        /* ( label for kdb_kintr and hardclock) */
        iret                            /* return to caller */

 int_from_intstack:
-       cmpl    EXT(int_stack_base),%esp        /* seemingly looping? */
+       CPU_NUMBER(%edx)
+       cmpl    CX(EXT(int_stack_base),%edx),%esp /* seemingly looping? */
        jb      stack_overflowed        /* if not: */
        call    EXT(interrupt)          /* call interrupt routine */
 _return_to_iret_i:                     /* ( label for kdb_kintr) */
diff --git a/i386/i386/mp_desc.c b/i386/i386/mp_desc.c
index bcf2fbe7..49ed9f94 100644
--- a/i386/i386/mp_desc.c
+++ b/i386/i386/mp_desc.c
@@ -24,25 +24,36 @@
  * the rights to redistribute these changes.
  */

-#if    NCPUS > 1
-
-#include <string.h>
-
 #include <kern/cpu_number.h>
 #include <kern/debug.h>
 #include <kern/printf.h>
+#include <kern/smp.h>
+#include <kern/startup.h>
+#include <kern/kmutex.h>
 #include <mach/machine.h>
 #include <mach/xen.h>
 #include <vm/vm_kern.h>

 #include <i386/mp_desc.h>
 #include <i386/lock.h>
+#include <i386/apic.h>
+#include <i386/locore.h>
+#include <i386/gdt.h>
+#include <i386at/idt.h>
+#include <i386at/int_init.h>
+#include <i386/cpu.h>
+#include <i386/smp.h>
+
 #include <i386at/model_dep.h>
 #include <machine/ktss.h>
+#include <machine/smp.h>
 #include <machine/tss.h>
 #include <machine/io_perm.h>
 #include <machine/vm_param.h>

+#include <i386at/acpi_parse_apic.h>
+#include <string.h>
+
 /*
  * The i386 needs an interrupt stack to keep the PCB stack from being
  * overrun by interrupts.  All interrupt stacks MUST lie at lower addresses
@@ -52,20 +63,35 @@
 /*
  * Addresses of bottom and top of interrupt stacks.
  */
-vm_offset_t    interrupt_stack[NCPUS];
 vm_offset_t    int_stack_top[NCPUS];
 vm_offset_t    int_stack_base[NCPUS];

-/*
- * Barrier address.
- */
-vm_offset_t    int_stack_high;
+/* Interrupt stack allocation */
+uint8_t solid_intstack[NCPUS*INTSTACK_SIZE] __aligned(NCPUS*INTSTACK_SIZE);
+
+void
+interrupt_stack_alloc(void)
+{
+       int i;
+
+       /*
+        * Set up pointers to the top of the interrupt stack.
+        */

+       for (i = 0; i < NCPUS; i++) {
+               int_stack_base[i] = (vm_offset_t) &solid_intstack[i * INTSTACK_SIZE];
+               int_stack_top[i] = (vm_offset_t) &solid_intstack[(i + 1) * INTSTACK_SIZE] - 4;
+       }
+}
+
+#if    NCPUS > 1
 /*
- * First cpu`s interrupt stack.
+ * Flag to mark SMP init by BSP complete
  */
-extern char            _intstack[];    /* bottom */
-extern char            _eintstack[];   /* top */
+int bspdone;
+
+extern void *apboot, *apbootend;
+extern volatile ApicLocalUnit* lapic;

 /*
  * Multiprocessor i386/i486 systems use a separate copy of the
@@ -77,7 +103,7 @@ extern char          _eintstack[];   /* top */
  */

 /*
- * Allocated descriptor tables.
+ * Descriptor tables.
  */
 struct mp_desc_table   *mp_desc_table[NCPUS] = { 0 };

@@ -102,12 +128,13 @@ extern struct real_descriptor     ldt[LDTSZ];
  * Allocate and initialize the per-processor descriptor tables.
  */

-struct mp_desc_table *
+int
 mp_desc_init(int mycpu)
 {
        struct mp_desc_table *mpt;
+       vm_offset_t mem;

-       if (mycpu == master_cpu) {
+       if (mycpu == 0) {
                /*
                 * Master CPU uses the tables built at boot time.
                 * Just set the TSS and GDT pointers.
@@ -118,61 +145,28 @@ mp_desc_init(int mycpu)
        }
        else {
                /*
-                * Other CPUs allocate the table from the bottom of
-                * the interrupt stack.
+                * Allocate tables for other CPUs
                 */
-               mpt = (struct mp_desc_table *) interrupt_stack[mycpu];
+               if (!init_alloc_aligned(sizeof(struct mp_desc_table), &mem))
+                       panic("not enough memory for descriptor tables");
+               mpt = (struct mp_desc_table *)phystokv(mem);

                mp_desc_table[mycpu] = mpt;
                mp_ktss[mycpu] = &mpt->ktss;
                mp_gdt[mycpu] = mpt->gdt;

                /*
-                * Copy the tables
+                * Zero the tables
                 */
-               memcpy(mpt->idt,
-                 idt,
-                 sizeof(idt));
-               memcpy(mpt->gdt,
-                 gdt,
-                 sizeof(gdt));
-               memcpy(mpt->ldt,
-                 ldt,
-                 sizeof(ldt));
-               memset(&mpt->ktss, 0,
-                 sizeof(struct task_tss));
+               memset(mpt->idt, 0, sizeof(idt));
+               memset(mpt->gdt, 0, sizeof(gdt));
+               memset(mpt->ldt, 0, sizeof(ldt));
+               memset(&mpt->ktss, 0, sizeof(struct task_tss));

-               /*
-                * Fix up the entries in the GDT to point to
-                * this LDT and this TSS.
-                */
-#ifdef MACH_RING1
-               panic("TODO %s:%d\n",__FILE__,__LINE__);
-#else  /* MACH_RING1 */
-               _fill_gdt_sys_descriptor(mpt->gdt, KERNEL_LDT,
-                       (unsigned)&mpt->ldt,
-                       LDTSZ * sizeof(struct real_descriptor) - 1,
-                       ACC_P|ACC_PL_K|ACC_LDT, 0);
-               _fill_gdt_sys_descriptor(mpt->gdt, KERNEL_TSS,
-                       (unsigned)&mpt->ktss,
-                       sizeof(struct task_tss) - 1,
-                       ACC_P|ACC_PL_K|ACC_TSS, 0);
-
-               mpt->ktss.tss.ss0 = KERNEL_DS;
-               mpt->ktss.tss.io_bit_map_offset = IOPB_INVAL;
-               mpt->ktss.barrier = 0xFF;
-#endif /* MACH_RING1 */
-
-               return mpt;
+               return mycpu;
        }
 }

-static kern_return_t intel_startCPU(int slot_num)
-{
-       printf("TODO: intel_startCPU\n");
-       return KERN_FAILURE;
-}
-
 /* XXX should be adjusted per CPU speed */
 int simple_lock_pause_loop = 100;

@@ -206,24 +200,125 @@ void
 interrupt_processor(int cpu)
 {
        printf("interrupt cpu %d\n",cpu);
+       smp_pmap_update(apic_get_cpu_apic_id(cpu));
+}
+
+void
+cpu_setup()
+{
+    unsigned apic_id = (((ApicLocalUnit*)phystokv(lapic_addr))->apic_id.r >> 24) & 0xff;
+    uint16_t cpu = apic_get_cpu_kernel_id(apic_id);
+
+    printf("AP=(%u) before\n", cpu);
+
+    pmap_make_temporary_mapping();
+    printf("AP=(%u) tempmap done\n", cpu);
+
+#ifndef MACH_HYP
+    /* Turn paging on.
+     * TODO: Why does setting the WP bit here cause a crash?
+     */
+    set_cr0(get_cr0() | CR0_PG /* | CR0_WP */);
+    set_cr0(get_cr0() & ~(CR0_CD | CR0_NW));
+    if (CPU_HAS_FEATURE(CPU_FEATURE_PGE))
+        set_cr4(get_cr4() | CR4_PGE);
+#endif  /* MACH_HYP */
+    flush_instr_queue();
+    printf("AP=(%u) paging done\n", cpu);
+
+    mp_desc_init(cpu);
+    printf("AP=(%u) mpdesc done\n", cpu);
+
+    ap_gdt_init(cpu);
+    printf("AP=(%u) gdt done\n", cpu);
+
+    ap_idt_init(cpu);
+    printf("AP=(%u) idt done\n", cpu);
+
+    ap_int_init(cpu);
+    printf("AP=(%u) int done\n", cpu);
+
+    ap_ldt_init(cpu);
+    printf("AP=(%u) ldt done\n", cpu);
+
+    ap_ktss_init(cpu);
+    printf("AP=(%u) ktss done\n", cpu);
+
+    pmap_remove_temporary_mapping();
+    printf("AP=(%u) remove tempmap done\n", cpu);
+
+    pmap_set_page_dir();
+    flush_tlb();
+    printf("AP=(%u) reset page dir done\n", cpu);
+
+    /* Initialize machine_slot fields with the cpu data */
+    machine_slot[cpu].cpu_subtype = CPU_SUBTYPE_AT386;
+    machine_slot[cpu].cpu_type = machine_slot[0].cpu_type;
+
+    lapic_enable();
+    cpu_launch_first_thread(THREAD_NULL);
+}
+
+void
+cpu_ap_main()
+{
+    do {
+        asm volatile ("pause" : : : "memory");
+    } while (!bspdone);
+
+    cpu_setup();
 }

 kern_return_t
 cpu_start(int cpu)
 {
-       if (machine_slot[cpu].running)
-               return KERN_FAILURE;
+    assert(machine_slot[cpu].running != TRUE);
+
+    uint16_t apic_id = apic_get_cpu_apic_id(cpu);
+
+    printf("Trying to enable: %d\n", apic_id);
+
+    smp_startup_cpu(apic_id, AP_BOOT_ADDR);

-       return intel_startCPU(cpu);
+    printf("Started cpu %d (lapic id %04x)\n", cpu, apic_id);
+
+    return KERN_SUCCESS;
 }

 void
 start_other_cpus(void)
 {
-       int cpu;
-       for (cpu = 0; cpu < NCPUS; cpu++)
-               if (cpu != cpu_number())
-                       cpu_start(cpu);
-}
+       unsigned long flags;
+
+       cpu_intr_save(&flags);
+
+       int ncpus = smp_get_numcpus();

+       //Copy cpu initialization assembly routine
+       memcpy((void*)phystokv(AP_BOOT_ADDR), (void*) &apboot,
+              (uint32_t)&apbootend - (uint32_t)&apboot);
+
+#ifndef APIC
+       lapic_enable(); /* Enable lapic only once */
+#endif
+       unsigned cpu;
+       bspdone = 0;
+       for (cpu = 1; cpu < ncpus; cpu++) {
+               machine_slot[cpu].running = FALSE;
+
+               //Start cpu
+               printf("Starting AP %d\n", cpu);
+               cpu_start(cpu);
+       }
+       printf("BSP: Completed SMP init\n");
+       bspdone = 1;
+
+       for (cpu = 1; cpu < ncpus; cpu++) {
+               do {
+                       asm volatile ("pause" : : : "memory");
+               } while (machine_slot[cpu].running == FALSE);
+       }
+
+        cpu_intr_restore(flags);
+}
 #endif /* NCPUS > 1 */
diff --git a/i386/i386/mp_desc.h b/i386/i386/mp_desc.h
index ede8775f..59d50e77 100644
--- a/i386/i386/mp_desc.h
+++ b/i386/i386/mp_desc.h
@@ -46,6 +46,8 @@
 #include "gdt.h"
 #include "ldt.h"

+#define AP_BOOT_ADDR   0x7000
+
 /*
  * The descriptor tables are together in a structure
  * allocated one per processor (except for the boot processor).
@@ -72,11 +74,12 @@ extern struct task_tss              *mp_ktss[NCPUS];
  */
 extern struct real_descriptor  *mp_gdt[NCPUS];

+extern uint8_t solid_intstack[];

 /*
  * Each CPU calls this routine to set up its descriptor tables.
  */
-extern struct mp_desc_table *  mp_desc_init(int);
+extern int mp_desc_init(int);


 extern void interrupt_processor(int cpu);
@@ -90,4 +93,6 @@ extern kern_return_t cpu_start(int cpu);

 extern kern_return_t cpu_control(int cpu, const int *info, unsigned int count);

+extern void interrupt_stack_alloc(void);
+
 #endif /* _I386_MP_DESC_H_ */
diff --git a/i386/i386at/boothdr.S b/i386/i386at/boothdr.S
index 82d4b34a..d1d1fa51 100644
--- a/i386/i386at/boothdr.S
+++ b/i386/i386at/boothdr.S
@@ -1,6 +1,6 @@

 #include <mach/machine/asm.h>
-
+#include <i386/apic.h>
 #include <i386/i386asm.h>

        /*
@@ -54,7 +54,18 @@ boot_entry:
        movw    %ax,%ss

        /* Switch to our own interrupt stack.  */
-       movl    $_intstack+INTSTACK_SIZE,%esp
+       movl    $solid_intstack+INTSTACK_SIZE-4, %esp
+       andl    $0xfffffff0,%esp
+
+       /* Enable local apic */
+       xorl    %eax, %eax
+       xorl    %edx, %edx
+       movl    $APIC_MSR, %ecx
+       rdmsr
+       orl     $APIC_MSR_ENABLE, %eax
+       orl     $APIC_MSR_BSP, %eax
+       movl    $APIC_MSR, %ecx
+       wrmsr

        /* Reset EFLAGS to a known state.  */
        pushl   $0
@@ -91,9 +102,6 @@ iplt_done:
        /* Jump into C code.  */
        call    EXT(c_boot_entry)

-       .comm   _intstack,INTSTACK_SIZE
-       .comm   _eintstack,0
-
 .align 16
        .word 0
 boot_gdt_descr:
diff --git a/i386/i386at/ioapic.c b/i386/i386at/ioapic.c
index 003690ed..1dd7af58 100644
--- a/i386/i386at/ioapic.c
+++ b/i386/i386at/ioapic.c
@@ -186,9 +186,9 @@ lapic_enable_timer(void)
     /* Some buggy hardware requires this set again */
     lapic->divider_config.r = LAPIC_TIMER_DIVIDE_16;

-    /* Enable interrupts for the first time on BSP */
+    /* Enable interrupts for the first time */
+    printf("LAPIC timer configured on cpu%d\n", cpu_number());
     asm("sti");
-    printf("LAPIC timer configured\n");
 }

 void
diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c
index 7a679ba4..cc18c864 100644
--- a/i386/i386at/model_dep.c
+++ b/i386/i386at/model_dep.c
@@ -134,11 +134,9 @@ extern char        version[];
 /* If set, reboot the system on ctrl-alt-delete.  */
 boolean_t      rebootflag = FALSE;     /* exported to kdintr */

-/* Interrupt stack.  */
-static char int_stack[KERNEL_STACK_SIZE] __aligned(KERNEL_STACK_SIZE);
-#if NCPUS <= 1
-vm_offset_t int_stack_top[1], int_stack_base[1];
-#endif
+/* Interrupt stacks  */
+extern vm_offset_t int_stack_top[], int_stack_base[];
+extern uint8_t solid_intstack[];    /* bottom */

 #ifdef LINUX_DEV
 extern void linux_init(void);
@@ -171,15 +169,18 @@ void machine_init(void)
        hyp_init();
 #else  /* MACH_HYP */

+#if (NCPUS > 1)
+       acpi_apic_init();
+       smp_init();
+#endif
 #if defined(APIC)
-       if (acpi_apic_init() != ACPI_SUCCESS) {
-               panic("APIC not found, unable to boot");
-       }
        ioapic_configure();
        lapic_enable_timer();
-#if (NCPUS > 1)
-       smp_init();
+#else
+       startrtclock();
+#endif

+#if defined(APIC)
 #warning FIXME: Rather unmask them from their respective drivers
        /* kd */
        unmask_irq(1);
@@ -187,8 +188,7 @@ void machine_init(void)
        unmask_irq(4);
        /* com1 */
        unmask_irq(3);
-#endif /* NCPUS > 1 */
-#endif /* APIC */
+#endif

 #ifdef LINUX_DEV
        /*
@@ -359,8 +359,6 @@ register_boot_data(const struct multiboot_raw_info *mbi)
 static void
 i386at_init(void)
 {
-       /* XXX move to intel/pmap.h */
-       extern pt_entry_t *kernel_page_dir;
        int i;

        /*
@@ -448,47 +446,8 @@ i386at_init(void)
         */
        biosmem_setup();

-       /*
-        * We'll have to temporarily install a direct mapping
-        * between physical memory and low linear memory,
-        * until we start using our new kernel segment descriptors.
-        */
-#if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS
-       vm_offset_t delta = INIT_VM_MIN_KERNEL_ADDRESS - LINEAR_MIN_KERNEL_ADDRESS;
-       if ((vm_offset_t)(-delta) < delta)
-               delta = (vm_offset_t)(-delta);
-       int nb_direct = delta >> PDESHIFT;
-       for (i = 0; i < nb_direct; i++)
-               kernel_page_dir[lin2pdenum_cont(INIT_VM_MIN_KERNEL_ADDRESS) + i] =
-                       kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS) + i];
-#endif
-       /* We need BIOS memory mapped at 0xc0000 & co for BIOS accesses */
-#if VM_MIN_KERNEL_ADDRESS != 0
-       kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)] =
-               kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS)];
-#endif
+       pmap_make_temporary_mapping();

-#ifdef MACH_PV_PAGETABLES
-       for (i = 0; i < PDPNUM; i++)
-               pmap_set_page_readonly_init((void*) kernel_page_dir + i * INTEL_PGBYTES);
-#if PAE
-       pmap_set_page_readonly_init(kernel_pmap->pdpbase);
-#endif /* PAE */
-#endif /* MACH_PV_PAGETABLES */
-#if PAE
-#ifdef __x86_64__
-       set_cr3((unsigned long)_kvtophys(kernel_pmap->l4base));
-#else
-       set_cr3((unsigned long)_kvtophys(kernel_pmap->pdpbase));
-#endif
-#ifndef        MACH_HYP
-       if (!CPU_HAS_FEATURE(CPU_FEATURE_PAE))
-               panic("CPU doesn't have support for PAE.");
-       set_cr4(get_cr4() | CR4_PAE);
-#endif /* MACH_HYP */
-#else
-       set_cr3((unsigned long)_kvtophys(kernel_page_dir));
-#endif /* PAE */
 #ifndef        MACH_HYP
        /* Turn paging on.
         * Also set the WP bit so that on 486 or better processors
@@ -520,40 +479,13 @@ i386at_init(void)
        mp_desc_init(0);
 #endif // NCPUS

-#if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS
-       /* Get rid of the temporary direct mapping and flush it out of the TLB.  */
-       for (i = 0 ; i < nb_direct; i++) {
-#ifdef MACH_XEN
-#ifdef MACH_PSEUDO_PHYS
-               if (!hyp_mmu_update_pte(kv_to_ma(&kernel_page_dir[lin2pdenum_cont(VM_MIN_KERNEL_ADDRESS) + i]), 0))
-#else  /* MACH_PSEUDO_PHYS */
-               if (hyp_do_update_va_mapping(VM_MIN_KERNEL_ADDRESS + i * INTEL_PGBYTES, 0, UVMF_INVLPG | UVMF_ALL))
-#endif /* MACH_PSEUDO_PHYS */
-                       printf("couldn't unmap frame %d\n", i);
-#else  /* MACH_XEN */
-               kernel_page_dir[lin2pdenum_cont(INIT_VM_MIN_KERNEL_ADDRESS) + i] = 0;
-#endif /* MACH_XEN */
-       }
-#endif
-       /* Keep BIOS memory mapped */
-#if VM_MIN_KERNEL_ADDRESS != 0
-       kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)] =
-               kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS)];
-#endif
-
-       /* Not used after boot, better give it back.  */
-#ifdef MACH_XEN
-       hyp_free_page(0, (void*) VM_MIN_KERNEL_ADDRESS);
-#endif /* MACH_XEN */
-
-       flush_tlb();
+       pmap_remove_temporary_mapping();

 #ifdef MACH_XEN
        hyp_p2m_init();
 #endif /* MACH_XEN */

-       int_stack_base[0] = (vm_offset_t)&int_stack;
-       int_stack_top[0] = int_stack_base[0] + KERNEL_STACK_SIZE - 4;
+       interrupt_stack_alloc();
 }

 /*
@@ -645,7 +577,6 @@ void c_boot_entry(vm_offset_t bi)
 #endif /* MACH_KDB */

        machine_slot[0].is_cpu = TRUE;
-       machine_slot[0].running = TRUE;
        machine_slot[0].cpu_subtype = CPU_SUBTYPE_AT386;

        switch (cpu_type)
@@ -693,6 +624,8 @@ startrtclock(void)
 {
 #ifndef APIC
        clkstart();
+       asm ("sti");
+       unmask_irq(0);
 #endif
 }

diff --git a/i386/i386at/model_dep.h b/i386/i386at/model_dep.h
index a972695f..f72ddc3b 100644
--- a/i386/i386at/model_dep.h
+++ b/i386/i386at/model_dep.h
@@ -28,10 +28,9 @@
 extern vm_offset_t int_stack_top[NCPUS], int_stack_base[NCPUS];

 /* Check whether P points to the interrupt stack.  */
-#define ON_INT_STACK(P)        (((P) & ~(KERNEL_STACK_SIZE-1)) == int_stack_base[0])
+#define ON_INT_STACK(P)        (((P) & ~(NCPUS*INTSTACK_SIZE-1)) == int_stack_base[0])

 extern vm_offset_t timemmap(dev_t dev, vm_offset_t off, vm_prot_t prot);
-
 void inittodr(void);

 boolean_t init_alloc_aligned(vm_size_t size, vm_offset_t *addrp);
diff --git a/i386/intel/pmap.c b/i386/intel/pmap.c
index 84a4cef5..5cd68878 100644
--- a/i386/intel/pmap.c
+++ b/i386/intel/pmap.c
@@ -396,6 +396,7 @@ boolean_t   cpu_update_needed[NCPUS];

 struct pmap    kernel_pmap_store;
 pmap_t         kernel_pmap;
+pt_entry_t     *kernel_page_dir;

 struct kmem_cache      pmap_cache;             /* cache of pmap structures */
 struct kmem_cache      pd_cache;               /* cache of page directories */
@@ -416,12 +417,6 @@ int                ptes_per_vm_page;       /* number of hardware ptes needed

 unsigned int   inuse_ptepages_count = 0;       /* debugging */

-/*
- * Pointer to the basic page directory for the kernel.
- * Initialized by pmap_bootstrap().
- */
-pt_entry_t *kernel_page_dir;
-
 /*
  * Two slots for temporary physical page mapping, to allow for
  * physical-to-physical transfers.
@@ -573,20 +568,17 @@ void pmap_bootstrap(void)
         * Mapping is turned off; we must reference only physical addresses.
         * The load image of the system is to be mapped 1-1 physical = virtual.
         */
-
        /*
         *      Set ptes_per_vm_page for general use.
         */
 #if 0
        ptes_per_vm_page = PAGE_SIZE / INTEL_PGBYTES;
 #endif
-
        /*
         *      The kernel's pmap is statically allocated so we don't
         *      have to use pmap_create, which is unlikely to work
         *      correctly at this part of the boot sequence.
         */
-
        kernel_pmap = &kernel_pmap_store;

 #if    NCPUS > 1
@@ -3008,3 +3000,96 @@ pmap_unmap_page_zero (void)
 #endif /* MACH_PV_PAGETABLES */
 }
 #endif /* __i386__ */
+
+void
+pmap_make_temporary_mapping(void)
+{
+       int i;
+
+       /*
+        * We'll have to temporarily install a direct mapping
+        * between physical memory and low linear memory,
+        * until we start using our new kernel segment descriptors.
+        */
+#if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS
+       vm_offset_t delta = INIT_VM_MIN_KERNEL_ADDRESS - LINEAR_MIN_KERNEL_ADDRESS;
+       if ((vm_offset_t)(-delta) < delta)
+               delta = (vm_offset_t)(-delta);
+       int nb_direct = delta >> PDESHIFT;
+       for (i = 0; i < nb_direct; i++)
+               kernel_page_dir[lin2pdenum_cont(INIT_VM_MIN_KERNEL_ADDRESS) + i] =
+                       kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS) + i];
+#endif
+       /* We need BIOS memory mapped at 0xc0000 & co for BIOS accesses */
+#if VM_MIN_KERNEL_ADDRESS != 0
+       kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)] =
+               kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS)];
+#endif
+
+#ifdef MACH_PV_PAGETABLES
+       for (i = 0; i < PDPNUM; i++)
+               pmap_set_page_readonly_init((void*) kernel_page_dir + i * INTEL_PGBYTES);
+#if PAE
+       pmap_set_page_readonly_init(kernel_pmap->pdpbase);
+#endif /* PAE */
+#endif /* MACH_PV_PAGETABLES */
+
+       pmap_set_page_dir();
+}
+
+void
+pmap_set_page_dir(void)
+{
+#if PAE
+#ifdef __x86_64__
+       set_cr3((unsigned long)_kvtophys(kernel_pmap->l4base));
+#else
+       set_cr3((unsigned long)_kvtophys(kernel_pmap->pdpbase));
+#endif
+#ifndef        MACH_HYP
+       if (!CPU_HAS_FEATURE(CPU_FEATURE_PAE))
+               panic("CPU doesn't have support for PAE.");
+       set_cr4(get_cr4() | CR4_PAE);
+#endif /* MACH_HYP */
+#else
+       set_cr3((unsigned long)_kvtophys(kernel_page_dir));
+#endif /* PAE */
+}
+
+void
+pmap_remove_temporary_mapping(void)
+{
+       int i;
+
+#if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS
+       vm_offset_t delta = INIT_VM_MIN_KERNEL_ADDRESS - LINEAR_MIN_KERNEL_ADDRESS;
+       if ((vm_offset_t)(-delta) < delta)
+               delta = (vm_offset_t)(-delta);
+       int nb_direct = delta >> PDESHIFT;
+       /* Get rid of the temporary direct mapping and flush it out of the TLB.  */
+       for (i = 0 ; i < nb_direct; i++) {
+#ifdef MACH_XEN
+#ifdef MACH_PSEUDO_PHYS
+               if (!hyp_mmu_update_pte(kv_to_ma(&kernel_page_dir[lin2pdenum_cont(VM_MIN_KERNEL_ADDRESS) + i]), 0))
+#else  /* MACH_PSEUDO_PHYS */
+               if (hyp_do_update_va_mapping(VM_MIN_KERNEL_ADDRESS + i * INTEL_PGBYTES, 0, UVMF_INVLPG | UVMF_ALL))
+#endif /* MACH_PSEUDO_PHYS */
+                       printf("couldn't unmap frame %d\n", i);
+#else  /* MACH_XEN */
+               kernel_page_dir[lin2pdenum_cont(INIT_VM_MIN_KERNEL_ADDRESS) + i] = 0;
+#endif /* MACH_XEN */
+       }
+#endif
+       /* Keep BIOS memory mapped */
+#if VM_MIN_KERNEL_ADDRESS != 0
+       kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)] =
+               kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS)];
+#endif
+
+       /* Not used after boot, better give it back.  */
+#ifdef MACH_XEN
+       hyp_free_page(0, (void*) VM_MIN_KERNEL_ADDRESS);
+#endif /* MACH_XEN */
+
+       flush_tlb();
+}
diff --git a/i386/intel/pmap.h b/i386/intel/pmap.h
index d6bf85fb..92247faa 100644
--- a/i386/intel/pmap.h
+++ b/i386/intel/pmap.h
@@ -475,6 +475,8 @@ pt_entry_t *pmap_pte(const pmap_t pmap, vm_offset_t addr);
 #define        pmap_attribute(pmap,addr,size,attr,value) \
                                        (KERN_INVALID_ADDRESS)

+extern pt_entry_t *kernel_page_dir;
+
 /*
  *  Bootstrap the system enough to run with virtual memory.
  *  Allocate the kernel page directory and page tables,
@@ -483,6 +485,10 @@ pt_entry_t *pmap_pte(const pmap_t pmap, vm_offset_t addr);
  */
 extern void pmap_bootstrap(void);

+extern void pmap_set_page_dir(void);
+extern void pmap_make_temporary_mapping(void);
+extern void pmap_remove_temporary_mapping(void);
+
 extern void pmap_unmap_page_zero (void);

 /*
diff --git a/linux/dev/arch/i386/kernel/irq.c b/linux/dev/arch/i386/kernel/irq.c
index 67feea84..6f99003e 100644
--- a/linux/dev/arch/i386/kernel/irq.c
+++ b/linux/dev/arch/i386/kernel/irq.c
@@ -31,6 +31,7 @@
 #include <i386/spl.h>
 #include <i386/irq.h>
 #include <i386/pit.h>
+#include <i386/model_dep.h>

 #define MACH_INCLUDE
 #include <linux/mm.h>
@@ -421,7 +422,7 @@ reserve_mach_irqs (void)
 {
   unsigned int i;

-  for (i = 0; i < NINTR; i++)
+  for (i = 1; i < NINTR; i++)
     {
       if (ivect[i] != intnull)
        /* This dummy action does not specify SA_SHIRQ, so
@@ -707,7 +708,6 @@ void
 init_IRQ (void)
 {
   char *p;
-  int latch = (CLKNUM + hz / 2) / hz;

   /*
    * Ensure interrupts are disabled.
@@ -715,19 +715,12 @@ init_IRQ (void)
   (void) splhigh ();

 #ifndef APIC
-  /*
-   * Program counter 0 of 8253 to interrupt hz times per second.
-   */
-  outb_p (PIT_C0 | PIT_SQUAREMODE | PIT_READMODE, PITCTL_PORT);
-  outb_p (latch & 0xff, PITCTR0_PORT);
-  outb (latch >> 8, PITCTR0_PORT);
-#endif
-
   /*
    * Install our clock interrupt handler.
    */
   old_clock_handler = ivect[0];
   ivect[0] = linux_timer_intr;
+#endif

   reserve_mach_irqs ();

diff --git a/linux/dev/init/main.c b/linux/dev/init/main.c
index 6d853957..207724f3 100644
--- a/linux/dev/init/main.c
+++ b/linux/dev/init/main.c
@@ -160,7 +160,9 @@ linux_init (void)
   pcmcia_init ();
 #endif

+#ifndef APIC
   restore_IRQ ();
+#endif

   linux_auto_config = 0;
 }
--
2.34.1




reply via email to

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