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 (<[email protected]>)
escribió:
> Also-by: Almudena Garcia <[email protected]>
> ---
> 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
>
>
>
>