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 (<dam...@zamaudio.com>) escribió: > Also-by: Almudena Garcia <liberamenso10...@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 > > > >