segmentless smp fixes
adjust the smp booting procedure for segmentless operation. changes are mostly due to gdt/idt being dependent on paging, because of the high location, and paging being on much sooner because of that too. also smaller fixes: redefine DESC_SIZE, fix kernel makefile variable name (crosscompiling), some null pointer checks that trap now because of a sparser pagetable, acpi sanity checking
This commit is contained in:
parent
50e2064049
commit
1d48c0148e
16 changed files with 259 additions and 145 deletions
|
@ -16,6 +16,14 @@ struct segdesc_s { /* segment descriptor for protected mode */
|
||||||
u8_t base_high;
|
u8_t base_high;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct gatedesc_s {
|
||||||
|
u16_t offset_low;
|
||||||
|
u16_t selector;
|
||||||
|
u8_t pad; /* |000|XXXXX| ig & trpg, |XXXXXXXX| task g */
|
||||||
|
u8_t p_dpl_type; /* |P|DL|0|TYPE| */
|
||||||
|
u16_t offset_high;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct desctableptr_s {
|
struct desctableptr_s {
|
||||||
u16_t limit;
|
u16_t limit;
|
||||||
u32_t base;
|
u32_t base;
|
||||||
|
|
|
@ -8,7 +8,7 @@ PROG= kernel
|
||||||
SRCS+= clock.c cpulocals.c interrupt.c main.c proc.c system.c \
|
SRCS+= clock.c cpulocals.c interrupt.c main.c proc.c system.c \
|
||||||
table.c utility.c
|
table.c utility.c
|
||||||
|
|
||||||
LINKERSCRIPT=${.CURDIR}/arch/${ARCH}/kernel.lds
|
LINKERSCRIPT=${.CURDIR}/arch/${MACHINE_ARCH}/kernel.lds
|
||||||
|
|
||||||
DPADD+= ${LIBTIMERS} ${LIBSYS} ${LIBEXEC} $(LINKERSCRIPT)
|
DPADD+= ${LIBTIMERS} ${LIBSYS} ${LIBEXEC} $(LINKERSCRIPT)
|
||||||
LDADD+= -ltimers -lsys -lexec
|
LDADD+= -ltimers -lsys -lexec
|
||||||
|
|
|
@ -39,6 +39,24 @@ static int acpi_check_signature(const char * orig, const char * match)
|
||||||
return strncmp(orig, match, ACPI_SDT_SIGNATURE_LEN);
|
return strncmp(orig, match, ACPI_SDT_SIGNATURE_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32_t acpi_phys2vir(u32_t p)
|
||||||
|
{
|
||||||
|
if(!vm_running) {
|
||||||
|
printf("acpi: returning 0x%lx as vir addr\n", p);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
panic("acpi: can't get virtual address of arbitrary physical address");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int acpi_phys_copy(phys_bytes phys, void *target, size_t len)
|
||||||
|
{
|
||||||
|
if(!vm_running) {
|
||||||
|
memcpy(target, (void *) phys, len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
panic("can't acpi_phys_copy with vm");
|
||||||
|
}
|
||||||
|
|
||||||
static int acpi_read_sdt_at(phys_bytes addr,
|
static int acpi_read_sdt_at(phys_bytes addr,
|
||||||
struct acpi_sdt_header * tb,
|
struct acpi_sdt_header * tb,
|
||||||
size_t size,
|
size_t size,
|
||||||
|
@ -172,7 +190,7 @@ static int get_acpi_rsdp(void)
|
||||||
/*
|
/*
|
||||||
* Read 40:0Eh - to find the starting address of the EBDA.
|
* Read 40:0Eh - to find the starting address of the EBDA.
|
||||||
*/
|
*/
|
||||||
phys_copy (0x40E, vir2phys(&ebda), sizeof(ebda));
|
acpi_phys_copy (0x40E, &ebda, sizeof(ebda));
|
||||||
if (ebda) {
|
if (ebda) {
|
||||||
ebda <<= 4;
|
ebda <<= 4;
|
||||||
if(platform_tbl_ptr(ebda, ebda + 0x400, 16, &acpi_rsdp,
|
if(platform_tbl_ptr(ebda, ebda + 0x400, 16, &acpi_rsdp,
|
||||||
|
@ -192,16 +210,10 @@ static int get_acpi_rsdp(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int acpi_read_kernel(phys_bytes addr, void * buff, size_t size)
|
|
||||||
{
|
|
||||||
phys_copy(addr, vir2phys(buff), size);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void acpi_init(void)
|
void acpi_init(void)
|
||||||
{
|
{
|
||||||
int s, i;
|
int s, i;
|
||||||
read_func = acpi_read_kernel;
|
read_func = acpi_phys_copy;
|
||||||
|
|
||||||
if (!get_acpi_rsdp()) {
|
if (!get_acpi_rsdp()) {
|
||||||
printf("WARNING : Cannot configure ACPI\n");
|
printf("WARNING : Cannot configure ACPI\n");
|
||||||
|
@ -238,7 +250,7 @@ struct acpi_madt_ioapic * acpi_get_ioapic_next(void)
|
||||||
|
|
||||||
if (idx == 0) {
|
if (idx == 0) {
|
||||||
madt_hdr = (struct acpi_madt_hdr *)
|
madt_hdr = (struct acpi_madt_hdr *)
|
||||||
phys2vir(acpi_get_table_base("APIC"));
|
acpi_phys2vir(acpi_get_table_base("APIC"));
|
||||||
if (madt_hdr == NULL)
|
if (madt_hdr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -260,7 +272,7 @@ struct acpi_madt_lapic * acpi_get_lapic_next(void)
|
||||||
|
|
||||||
if (idx == 0) {
|
if (idx == 0) {
|
||||||
madt_hdr = (struct acpi_madt_hdr *)
|
madt_hdr = (struct acpi_madt_hdr *)
|
||||||
phys2vir(acpi_get_table_base("APIC"));
|
acpi_phys2vir(acpi_get_table_base("APIC"));
|
||||||
if (madt_hdr == NULL)
|
if (madt_hdr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -365,6 +365,11 @@ void ioapic_disable_all(void)
|
||||||
|
|
||||||
static void ioapic_disable_irq(unsigned irq)
|
static void ioapic_disable_irq(unsigned irq)
|
||||||
{
|
{
|
||||||
|
if(!(io_apic_irq[irq].ioa)) {
|
||||||
|
printf("ioapic_disable_irq: no ioa set for irq %d!\n", irq);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assert(io_apic_irq[irq].ioa);
|
assert(io_apic_irq[irq].ioa);
|
||||||
|
|
||||||
ioapic_disable_pin(io_apic_irq[irq].ioa->addr, io_apic_irq[irq].pin);
|
ioapic_disable_pin(io_apic_irq[irq].ioa->addr, io_apic_irq[irq].pin);
|
||||||
|
@ -373,6 +378,11 @@ static void ioapic_disable_irq(unsigned irq)
|
||||||
|
|
||||||
static void ioapic_enable_irq(unsigned irq)
|
static void ioapic_enable_irq(unsigned irq)
|
||||||
{
|
{
|
||||||
|
if(!(io_apic_irq[irq].ioa)) {
|
||||||
|
printf("ioapic_enable_irq: no ioa set for irq %d!\n", irq);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assert(io_apic_irq[irq].ioa);
|
assert(io_apic_irq[irq].ioa);
|
||||||
|
|
||||||
ioapic_enable_pin(io_apic_irq[irq].ioa->addr, io_apic_irq[irq].pin);
|
ioapic_enable_pin(io_apic_irq[irq].ioa->addr, io_apic_irq[irq].pin);
|
||||||
|
@ -915,16 +925,17 @@ static int acpi_get_ioapics(struct io_apic * ioa, unsigned * nioa, unsigned max)
|
||||||
if (acpi_ioa == NULL)
|
if (acpi_ioa == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
assert(acpi_ioa->address);
|
||||||
|
|
||||||
ioa[n].id = acpi_ioa->id;
|
ioa[n].id = acpi_ioa->id;
|
||||||
ioa[n].addr = acpi_ioa->address;
|
ioa[n].addr = acpi_ioa->address;
|
||||||
ioa[n].paddr = (phys_bytes) acpi_ioa->address;
|
ioa[n].paddr = (phys_bytes) acpi_ioa->address;
|
||||||
ioa[n].gsi_base = acpi_ioa->global_int_base;
|
ioa[n].gsi_base = acpi_ioa->global_int_base;
|
||||||
ioa[n].pins = ((ioapic_read(ioa[n].addr,
|
ioa[n].pins = ((ioapic_read(ioa[n].addr,
|
||||||
IOAPIC_VERSION) & 0xff0000) >> 16)+1;
|
IOAPIC_VERSION) & 0xff0000) >> 16)+1;
|
||||||
printf("IO APIC %d addr 0x%lx paddr 0x%lx pins %d\n",
|
printf("IO APIC idx %d id %d addr 0x%lx paddr 0x%lx pins %d\n",
|
||||||
acpi_ioa->id, ioa[n].addr, ioa[n].paddr,
|
n, acpi_ioa->id, ioa[n].addr, ioa[n].paddr,
|
||||||
ioa[n].pins);
|
ioa[n].pins);
|
||||||
|
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -206,6 +206,7 @@ void context_stop(struct proc * p)
|
||||||
u64_t * __tsc_ctr_switch = get_cpulocal_var_ptr(tsc_ctr_switch);
|
u64_t * __tsc_ctr_switch = get_cpulocal_var_ptr(tsc_ctr_switch);
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
unsigned cpu = cpuid;
|
unsigned cpu = cpuid;
|
||||||
|
int must_bkl_unlock = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is called only if we switch from kernel to user or idle
|
* This function is called only if we switch from kernel to user or idle
|
||||||
|
@ -222,7 +223,7 @@ void context_stop(struct proc * p)
|
||||||
tmp = sub64(tsc, *__tsc_ctr_switch);
|
tmp = sub64(tsc, *__tsc_ctr_switch);
|
||||||
kernel_ticks[cpu] = add64(kernel_ticks[cpu], tmp);
|
kernel_ticks[cpu] = add64(kernel_ticks[cpu], tmp);
|
||||||
p->p_cycles = add64(p->p_cycles, tmp);
|
p->p_cycles = add64(p->p_cycles, tmp);
|
||||||
BKL_UNLOCK();
|
must_bkl_unlock = 1;
|
||||||
} else {
|
} else {
|
||||||
u64_t bkl_tsc;
|
u64_t bkl_tsc;
|
||||||
atomic_t succ;
|
atomic_t succ;
|
||||||
|
@ -295,6 +296,12 @@ void context_stop(struct proc * p)
|
||||||
}
|
}
|
||||||
|
|
||||||
*__tsc_ctr_switch = tsc;
|
*__tsc_ctr_switch = tsc;
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
if(must_bkl_unlock) {
|
||||||
|
BKL_UNLOCK();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void context_stop_idle(void)
|
void context_stop_idle(void)
|
||||||
|
|
|
@ -11,7 +11,10 @@
|
||||||
#include "arch_proto.h"
|
#include "arch_proto.h"
|
||||||
#include "kernel/glo.h"
|
#include "kernel/glo.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <machine/archtypes.h>
|
||||||
|
#include <archconst.h>
|
||||||
#include <machine/cmos.h>
|
#include <machine/cmos.h>
|
||||||
#include <machine/bios.h>
|
#include <machine/bios.h>
|
||||||
#include <minix/portio.h>
|
#include <minix/portio.h>
|
||||||
|
@ -31,8 +34,9 @@ void trampoline(void);
|
||||||
* They have to be in location which is reachable using absolute addressing in
|
* They have to be in location which is reachable using absolute addressing in
|
||||||
* 16-bit mode
|
* 16-bit mode
|
||||||
*/
|
*/
|
||||||
extern volatile u32_t __ap_id;
|
extern volatile u32_t __ap_id, __ap_pt;
|
||||||
extern volatile struct desctableptr_s __ap_gdt, __ap_idt;
|
extern volatile struct desctableptr_s __ap_gdt, __ap_idt;
|
||||||
|
extern u32_t __ap_gdt_tab, __ap_idt_tab;
|
||||||
extern void * __trampoline_end;
|
extern void * __trampoline_end;
|
||||||
|
|
||||||
extern u32_t busclock[CONFIG_MAX_CPUS];
|
extern u32_t busclock[CONFIG_MAX_CPUS];
|
||||||
|
@ -50,81 +54,84 @@ SPINLOCK_DEFINE(dispq_lock)
|
||||||
|
|
||||||
static void smp_reinit_vars(void);
|
static void smp_reinit_vars(void);
|
||||||
|
|
||||||
|
/* These are initialized in protect.c */
|
||||||
|
extern struct segdesc_s gdt[GDT_SIZE];
|
||||||
|
extern struct gatedesc_s idt[IDT_SIZE];
|
||||||
|
extern struct tss_s tss[CONFIG_MAX_CPUS];
|
||||||
|
extern int prot_init_done; /* Indicates they are ready */
|
||||||
|
|
||||||
|
static phys_bytes trampoline_base;
|
||||||
|
|
||||||
|
static u32_t ap_lin_addr(void *vaddr)
|
||||||
|
{
|
||||||
|
assert(trampoline_base);
|
||||||
|
return (u32_t) vaddr - (u32_t) &trampoline + trampoline_base;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* copies the 16-bit AP trampoline code to the first 1M of memory
|
* copies the 16-bit AP trampoline code to the first 1M of memory
|
||||||
*/
|
*/
|
||||||
static phys_bytes copy_trampoline(void)
|
void copy_trampoline(void)
|
||||||
{
|
{
|
||||||
char * s, *end;
|
char * s, *end;
|
||||||
phys_bytes tramp_base = 0;
|
unsigned tramp_size, tramp_start = (unsigned)&trampoline;;
|
||||||
unsigned tramp_size;
|
|
||||||
|
|
||||||
tramp_size = (unsigned) &__trampoline_end - (unsigned)&trampoline;
|
/* The trampoline code/data is made to be page-aligned. */
|
||||||
s = env_get("memory");
|
assert(!(tramp_start % I386_PAGE_SIZE));
|
||||||
if (!s)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while (*s != 0) {
|
tramp_size = (unsigned) &__trampoline_end - tramp_start;
|
||||||
phys_bytes base = 0xfffffff;
|
trampoline_base = alloc_lowest(&kinfo, tramp_size);
|
||||||
unsigned size;
|
|
||||||
/* Read fresh base and expect colon as next char. */
|
|
||||||
base = strtoul(s, &end, 0x10); /* get number */
|
|
||||||
if (end != s && *end == ':')
|
|
||||||
s = ++end; /* skip ':' */
|
|
||||||
else
|
|
||||||
*s=0;
|
|
||||||
|
|
||||||
/* Read fresh size and expect comma or assume end. */
|
/* The memory allocator finds the lowest available memory..
|
||||||
size = strtoul(s, &end, 0x10); /* get number */
|
* Verify it's low enough
|
||||||
if (end != s && *end == ',')
|
*/
|
||||||
s = ++end; /* skip ',' */
|
assert(trampoline_base + tramp_size < (1 << 20));
|
||||||
|
|
||||||
tramp_base = (base + 0xfff) & ~(0xfff);
|
/* prepare gdt and idt for the new cpus; make copies
|
||||||
/* the address must be less than 1M */
|
* of both the tables and the descriptors of them
|
||||||
if (tramp_base >= (1 << 20))
|
* in their boot addressing environment.
|
||||||
continue;
|
*/
|
||||||
if (size - (tramp_base - base) < tramp_size)
|
assert(prot_init_done);
|
||||||
continue;
|
memcpy(&__ap_gdt_tab, gdt, sizeof(gdt));
|
||||||
break;
|
memcpy(&__ap_idt_tab, gdt, sizeof(idt));
|
||||||
}
|
__ap_gdt.base = ap_lin_addr(&__ap_gdt_tab);
|
||||||
|
__ap_gdt.limit = sizeof(gdt)-1;
|
||||||
|
__ap_idt.base = ap_lin_addr(&__ap_idt_tab);
|
||||||
|
__ap_idt.limit = sizeof(idt)-1;
|
||||||
|
|
||||||
phys_copy(vir2phys(trampoline), tramp_base, tramp_size);
|
phys_copy(trampoline, trampoline_base, tramp_size);
|
||||||
|
|
||||||
return tramp_base;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct desctableptr_s gdt_desc, idt_desc;
|
extern int booting_cpu; /* tell protect.c what to do */
|
||||||
|
|
||||||
static void smp_start_aps(void)
|
static void smp_start_aps(void)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* Find an address and align it to a 4k boundary.
|
|
||||||
*/
|
|
||||||
unsigned cpu;
|
unsigned cpu;
|
||||||
u32_t biosresetvector;
|
u32_t biosresetvector, *newptpos;
|
||||||
phys_bytes trampoline_base, __ap_id_phys;
|
phys_bytes __ap_id_phys;
|
||||||
|
struct proc *bootstrap_pt = get_cpulocal_var(ptproc);
|
||||||
|
|
||||||
/* TODO hack around the alignment problem */
|
/* TODO hack around the alignment problem */
|
||||||
|
|
||||||
phys_copy (0x467, vir2phys(&biosresetvector), sizeof(u32_t));
|
phys_copy (0x467, &biosresetvector, sizeof(u32_t));
|
||||||
|
|
||||||
/* set the bios shutdown code to 0xA */
|
/* set the bios shutdown code to 0xA */
|
||||||
outb(RTC_INDEX, 0xF);
|
outb(RTC_INDEX, 0xF);
|
||||||
outb(RTC_IO, 0xA);
|
outb(RTC_IO, 0xA);
|
||||||
|
|
||||||
/* prepare gdt and idt for the new cpus */
|
assert(bootstrap_pt);
|
||||||
__ap_gdt = gdt_desc;
|
assert(bootstrap_pt->p_seg.p_cr3);
|
||||||
__ap_idt = idt_desc;
|
__ap_pt = bootstrap_pt->p_seg.p_cr3;
|
||||||
|
assert(__ap_pt);
|
||||||
|
|
||||||
if (!(trampoline_base = copy_trampoline())) {
|
copy_trampoline();
|
||||||
printf("Copying trampoline code failed, cannot boot SMP\n");
|
|
||||||
ncpus = 1;
|
/* New locations for cpu id, pagetable root */
|
||||||
}
|
|
||||||
__ap_id_phys = trampoline_base +
|
__ap_id_phys = trampoline_base +
|
||||||
(phys_bytes) &__ap_id - (phys_bytes)&trampoline;
|
(phys_bytes) &__ap_id - (phys_bytes)&trampoline;
|
||||||
|
|
||||||
/* setup the warm reset vector */
|
/* setup the warm reset vector */
|
||||||
phys_copy(vir2phys(&trampoline_base), 0x467, sizeof(u32_t));
|
phys_copy(&trampoline_base, 0x467, sizeof(u32_t));
|
||||||
|
|
||||||
/* okay, we're ready to go. boot all of the ap's now. we loop through
|
/* okay, we're ready to go. boot all of the ap's now. we loop through
|
||||||
* using the processor's apic id values.
|
* using the processor's apic id values.
|
||||||
|
@ -137,9 +144,8 @@ static void smp_start_aps(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
__ap_id = cpu;
|
__ap_id = booting_cpu = cpu;
|
||||||
phys_copy(vir2phys((void *) &__ap_id),
|
phys_copy((void *) &__ap_id, __ap_id_phys, sizeof(__ap_id));
|
||||||
__ap_id_phys, sizeof(__ap_id));
|
|
||||||
mfence();
|
mfence();
|
||||||
if (apic_send_init_ipi(cpu, trampoline_base) ||
|
if (apic_send_init_ipi(cpu, trampoline_base) ||
|
||||||
apic_send_startup_ipi(cpu, trampoline_base)) {
|
apic_send_startup_ipi(cpu, trampoline_base)) {
|
||||||
|
@ -161,7 +167,7 @@ static void smp_start_aps(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
phys_copy(vir2phys(&biosresetvector),(phys_bytes)0x467,sizeof(u32_t));
|
phys_copy(&biosresetvector,(phys_bytes)0x467,sizeof(u32_t));
|
||||||
|
|
||||||
outb(RTC_INDEX, 0xF);
|
outb(RTC_INDEX, 0xF);
|
||||||
outb(RTC_IO, 0);
|
outb(RTC_IO, 0);
|
||||||
|
@ -219,9 +225,6 @@ static void ap_finish_booting(void)
|
||||||
/* inform the world of our presence. */
|
/* inform the world of our presence. */
|
||||||
ap_cpu_ready = cpu;
|
ap_cpu_ready = cpu;
|
||||||
|
|
||||||
while(!bootstrap_pagetable_done)
|
|
||||||
arch_pause();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finish processor initialisation. CPUs must be excluded from running.
|
* Finish processor initialisation. CPUs must be excluded from running.
|
||||||
* lapic timer calibration locks and unlocks the BKL because of the
|
* lapic timer calibration locks and unlocks the BKL because of the
|
||||||
|
@ -231,14 +234,7 @@ static void ap_finish_booting(void)
|
||||||
spinlock_lock(&boot_lock);
|
spinlock_lock(&boot_lock);
|
||||||
BKL_LOCK();
|
BKL_LOCK();
|
||||||
|
|
||||||
/*
|
printf("CPU %d is up\n", cpu);
|
||||||
* we must load some page tables befre we turn paging on. As VM is
|
|
||||||
* always present we use those
|
|
||||||
*/
|
|
||||||
pg_load(); /* load bootstrap pagetable built by BSP */
|
|
||||||
vm_enable_paging();
|
|
||||||
|
|
||||||
printf("CPU %d paging is on\n", cpu);
|
|
||||||
|
|
||||||
cpu_identify();
|
cpu_identify();
|
||||||
|
|
||||||
|
|
|
@ -161,12 +161,13 @@ u32_t read_ds(void);
|
||||||
u32_t read_ss(void);
|
u32_t read_ss(void);
|
||||||
|
|
||||||
void add_memmap(kinfo_t *cbi, u64_t addr, u64_t len);
|
void add_memmap(kinfo_t *cbi, u64_t addr, u64_t len);
|
||||||
|
phys_bytes alloc_lowest(kinfo_t *cbi, phys_bytes len);
|
||||||
void vm_enable_paging(void);
|
void vm_enable_paging(void);
|
||||||
void cut_memmap(kinfo_t *cbi, phys_bytes start, phys_bytes end);
|
void cut_memmap(kinfo_t *cbi, phys_bytes start, phys_bytes end);
|
||||||
phys_bytes pg_roundup(phys_bytes b);
|
phys_bytes pg_roundup(phys_bytes b);
|
||||||
void pg_info(reg_t *, u32_t **);
|
void pg_info(reg_t *, u32_t **);
|
||||||
void pg_clear(void);
|
void pg_clear(void);
|
||||||
void pg_identity(void);
|
void pg_identity(kinfo_t *);
|
||||||
phys_bytes pg_load(void);
|
phys_bytes pg_load(void);
|
||||||
void pg_map(phys_bytes phys, vir_bytes vaddr, vir_bytes vaddr_end, kinfo_t *cbi);
|
void pg_map(phys_bytes phys, vir_bytes vaddr, vir_bytes vaddr_end, kinfo_t *cbi);
|
||||||
int pg_mapkernel(void);
|
int pg_mapkernel(void);
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#define LDT_SELECTOR SEG_SELECTOR(LDT_INDEX)
|
#define LDT_SELECTOR SEG_SELECTOR(LDT_INDEX)
|
||||||
#define TSS_SELECTOR(cpu) SEG_SELECTOR(TSS_INDEX(cpu))
|
#define TSS_SELECTOR(cpu) SEG_SELECTOR(TSS_INDEX(cpu))
|
||||||
|
|
||||||
|
#define DESC_SIZE 8
|
||||||
|
|
||||||
/* Privileges. */
|
/* Privileges. */
|
||||||
#define INTR_PRIVILEGE 0 /* kernel and interrupt handlers */
|
#define INTR_PRIVILEGE 0 /* kernel and interrupt handlers */
|
||||||
#define USER_PRIVILEGE 3 /* servers and user processes */
|
#define USER_PRIVILEGE 3 /* servers and user processes */
|
||||||
|
|
|
@ -164,11 +164,11 @@ static int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr,
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
unsigned cpu = cpuid;
|
unsigned cpu = cpuid;
|
||||||
|
|
||||||
if (GET_BIT(srcproc->p_stale_tlb, cpu)) {
|
if (srcproc && GET_BIT(srcproc->p_stale_tlb, cpu)) {
|
||||||
changed = 1;
|
changed = 1;
|
||||||
UNSET_BIT(srcproc->p_stale_tlb, cpu);
|
UNSET_BIT(srcproc->p_stale_tlb, cpu);
|
||||||
}
|
}
|
||||||
if (GET_BIT(dstproc->p_stale_tlb, cpu)) {
|
if (dstproc && GET_BIT(dstproc->p_stale_tlb, cpu)) {
|
||||||
changed = 1;
|
changed = 1;
|
||||||
UNSET_BIT(dstproc->p_stale_tlb, cpu);
|
UNSET_BIT(dstproc->p_stale_tlb, cpu);
|
||||||
}
|
}
|
||||||
|
@ -815,10 +815,13 @@ int arch_phys_map(const int index,
|
||||||
*flags = VMMF_UNCACHED;
|
*flags = VMMF_UNCACHED;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
else if (ioapic_enabled && index <= ioapic_last_index) {
|
else if (ioapic_enabled && index >= ioapic_first_index && index <= ioapic_last_index) {
|
||||||
*addr = io_apic[index - 1].paddr;
|
int ioapic_idx = index - ioapic_first_index;
|
||||||
|
*addr = io_apic[ioapic_idx].paddr;
|
||||||
|
assert(*addr);
|
||||||
*len = 4 << 10 /* 4kB */;
|
*len = 4 << 10 /* 4kB */;
|
||||||
*flags = VMMF_UNCACHED;
|
*flags = VMMF_UNCACHED;
|
||||||
|
printf("ioapic map: addr 0x%lx\n", *addr);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -479,27 +479,22 @@ ENTRY(startup_ap_32)
|
||||||
/*
|
/*
|
||||||
* we are in protected mode now, %cs is correct and we need to set the
|
* we are in protected mode now, %cs is correct and we need to set the
|
||||||
* data descriptors before we can touch anything
|
* data descriptors before we can touch anything
|
||||||
|
*
|
||||||
|
* first load the regular, highly mapped idt, gdt
|
||||||
*/
|
*/
|
||||||
movw $KERN_DS_SELECTOR, %ax
|
|
||||||
mov %ax, %ds
|
|
||||||
mov %ax, %ss
|
|
||||||
mov %ax, %es
|
|
||||||
movw $0, %ax
|
|
||||||
mov %ax, %fs
|
|
||||||
mov %ax, %gs
|
|
||||||
|
|
||||||
/* load TSS for this cpu which was prepared by BSP */
|
|
||||||
movl _C_LABEL(__ap_id), %ecx
|
|
||||||
shl $3, %cx
|
|
||||||
mov $TSS_SELECTOR(0), %eax
|
|
||||||
add %cx, %ax
|
|
||||||
ltr %ax
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* use the boot stack for now. The running CPUs are already using their
|
* use the boot stack for now. The running CPUs are already using their
|
||||||
* own stack, the rest is still waiting to be booted
|
* own stack, the rest is still waiting to be booted
|
||||||
*/
|
*/
|
||||||
|
movw $KERN_DS_SELECTOR, %ax
|
||||||
|
mov %ax, %ds
|
||||||
|
mov %ax, %ss
|
||||||
mov $_C_LABEL(k_boot_stktop) - 4, %esp
|
mov $_C_LABEL(k_boot_stktop) - 4, %esp
|
||||||
|
|
||||||
|
/* load the highly mapped idt, gdt, per-cpu tss */
|
||||||
|
call _C_LABEL(prot_load_selectors)
|
||||||
|
|
||||||
jmp _C_LABEL(smp_ap_boot)
|
jmp _C_LABEL(smp_ap_boot)
|
||||||
hlt
|
hlt
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,6 +22,17 @@ static phys_bytes kern_kernlen = (phys_bytes) &_kern_size;
|
||||||
/* page directory we can use to map things */
|
/* page directory we can use to map things */
|
||||||
static u32_t pagedir[1024] __aligned(4096);
|
static u32_t pagedir[1024] __aligned(4096);
|
||||||
|
|
||||||
|
void print_memmap(kinfo_t *cbi)
|
||||||
|
{
|
||||||
|
int m;
|
||||||
|
assert(cbi->mmap_size < MAXMEMMAP);
|
||||||
|
for(m = 0; m < cbi->mmap_size; m++) {
|
||||||
|
phys_bytes addr = cbi->memmap[m].addr, endit = cbi->memmap[m].addr + cbi->memmap[m].len;
|
||||||
|
printf("%08lx-%08lx ",addr, endit);
|
||||||
|
}
|
||||||
|
printf("\nsize %08lx\n", cbi->mmap_size);
|
||||||
|
}
|
||||||
|
|
||||||
void cut_memmap(kinfo_t *cbi, phys_bytes start, phys_bytes end)
|
void cut_memmap(kinfo_t *cbi, phys_bytes start, phys_bytes end)
|
||||||
{
|
{
|
||||||
int m;
|
int m;
|
||||||
|
@ -32,6 +43,8 @@ void cut_memmap(kinfo_t *cbi, phys_bytes start, phys_bytes end)
|
||||||
if((o=end % I386_PAGE_SIZE))
|
if((o=end % I386_PAGE_SIZE))
|
||||||
end += I386_PAGE_SIZE - o;
|
end += I386_PAGE_SIZE - o;
|
||||||
|
|
||||||
|
assert(kernel_may_alloc);
|
||||||
|
|
||||||
for(m = 0; m < cbi->mmap_size; m++) {
|
for(m = 0; m < cbi->mmap_size; m++) {
|
||||||
phys_bytes substart = start, subend = end;
|
phys_bytes substart = start, subend = end;
|
||||||
phys_bytes memaddr = cbi->memmap[m].addr,
|
phys_bytes memaddr = cbi->memmap[m].addr,
|
||||||
|
@ -53,10 +66,29 @@ void cut_memmap(kinfo_t *cbi, phys_bytes start, phys_bytes end)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
phys_bytes alloc_lowest(kinfo_t *cbi, phys_bytes len)
|
||||||
|
{
|
||||||
|
/* Allocate the lowest physical page we have. */
|
||||||
|
int m;
|
||||||
|
#define EMPTY 0xffffffff
|
||||||
|
phys_bytes lowest = EMPTY;
|
||||||
|
assert(len > 0);
|
||||||
|
len = roundup(len, I386_PAGE_SIZE);
|
||||||
|
|
||||||
|
assert(kernel_may_alloc);
|
||||||
|
|
||||||
|
for(m = 0; m < cbi->mmap_size; m++) {
|
||||||
|
if(cbi->memmap[m].len < len) continue;
|
||||||
|
if(cbi->memmap[m].addr < lowest) lowest = cbi->memmap[m].addr;
|
||||||
|
}
|
||||||
|
assert(lowest != EMPTY);
|
||||||
|
cut_memmap(cbi, lowest, len);
|
||||||
|
return lowest;
|
||||||
|
}
|
||||||
|
|
||||||
void add_memmap(kinfo_t *cbi, u64_t addr, u64_t len)
|
void add_memmap(kinfo_t *cbi, u64_t addr, u64_t len)
|
||||||
{
|
{
|
||||||
int m;
|
int m;
|
||||||
phys_bytes highmark;
|
|
||||||
#define LIMIT 0xFFFFF000
|
#define LIMIT 0xFFFFF000
|
||||||
/* Truncate available memory at 4GB as the rest of minix
|
/* Truncate available memory at 4GB as the rest of minix
|
||||||
* currently can't deal with any bigger.
|
* currently can't deal with any bigger.
|
||||||
|
@ -69,20 +101,25 @@ void add_memmap(kinfo_t *cbi, u64_t addr, u64_t len)
|
||||||
if(len == 0) return;
|
if(len == 0) return;
|
||||||
addr = roundup(addr, I386_PAGE_SIZE);
|
addr = roundup(addr, I386_PAGE_SIZE);
|
||||||
len = rounddown(len, I386_PAGE_SIZE);
|
len = rounddown(len, I386_PAGE_SIZE);
|
||||||
|
|
||||||
|
assert(kernel_may_alloc);
|
||||||
|
|
||||||
for(m = 0; m < MAXMEMMAP; m++) {
|
for(m = 0; m < MAXMEMMAP; m++) {
|
||||||
|
phys_bytes highmark;
|
||||||
if(cbi->memmap[m].len) continue;
|
if(cbi->memmap[m].len) continue;
|
||||||
cbi->memmap[m].addr = addr;
|
cbi->memmap[m].addr = addr;
|
||||||
cbi->memmap[m].len = len;
|
cbi->memmap[m].len = len;
|
||||||
cbi->memmap[m].type = MULTIBOOT_MEMORY_AVAILABLE;
|
cbi->memmap[m].type = MULTIBOOT_MEMORY_AVAILABLE;
|
||||||
if(m >= cbi->mmap_size)
|
if(m >= cbi->mmap_size)
|
||||||
cbi->mmap_size = m+1;
|
cbi->mmap_size = m+1;
|
||||||
|
highmark = addr + len;
|
||||||
|
if(highmark > cbi->mem_high_phys) {
|
||||||
|
cbi->mem_high_phys = highmark;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
highmark = addr + len;
|
|
||||||
if(highmark > cbi->mem_high_phys)
|
|
||||||
cbi->mem_high_phys = highmark;
|
|
||||||
|
|
||||||
panic("no available memmap slot");
|
panic("no available memmap slot");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +142,9 @@ phys_bytes pg_alloc_page(kinfo_t *cbi)
|
||||||
{
|
{
|
||||||
int m;
|
int m;
|
||||||
multiboot_memory_map_t *mmap;
|
multiboot_memory_map_t *mmap;
|
||||||
|
|
||||||
|
assert(kernel_may_alloc);
|
||||||
|
|
||||||
for(m = cbi->mmap_size-1; m >= 0; m--) {
|
for(m = cbi->mmap_size-1; m >= 0; m--) {
|
||||||
mmap = &cbi->memmap[m];
|
mmap = &cbi->memmap[m];
|
||||||
if(!mmap->len) continue;
|
if(!mmap->len) continue;
|
||||||
|
@ -120,16 +160,26 @@ phys_bytes pg_alloc_page(kinfo_t *cbi)
|
||||||
panic("can't find free memory");
|
panic("can't find free memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
void pg_identity(void)
|
void pg_identity(kinfo_t *cbi)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
phys_bytes phys;
|
phys_bytes phys;
|
||||||
|
|
||||||
|
/* We map memory that does not correspond to physical memory
|
||||||
|
* as non-cacheable. Make sure we know what it is.
|
||||||
|
*/
|
||||||
|
assert(cbi->mem_high_phys);
|
||||||
|
|
||||||
/* Set up an identity mapping page directory */
|
/* Set up an identity mapping page directory */
|
||||||
for(i = 0; i < I386_VM_DIR_ENTRIES; i++) {
|
for(i = 0; i < I386_VM_DIR_ENTRIES; i++) {
|
||||||
|
u32_t flags = I386_VM_PRESENT | I386_VM_BIGPAGE |
|
||||||
|
I386_VM_USER | I386_VM_WRITE;
|
||||||
|
if((cbi->mem_high_phys & I386_VM_ADDR_MASK_4MB)
|
||||||
|
<= (phys & I386_VM_ADDR_MASK_4MB)) {
|
||||||
|
flags |= I386_VM_PWT | I386_VM_PCD;
|
||||||
|
}
|
||||||
phys = i * I386_BIG_PAGE_SIZE;
|
phys = i * I386_BIG_PAGE_SIZE;
|
||||||
pagedir[i] = phys | I386_VM_PRESENT | I386_VM_BIGPAGE |
|
pagedir[i] = phys | flags;
|
||||||
I386_VM_USER | I386_VM_WRITE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,6 +266,8 @@ void pg_map(phys_bytes phys, vir_bytes vaddr, vir_bytes vaddr_end,
|
||||||
static u32_t *pt = NULL;
|
static u32_t *pt = NULL;
|
||||||
int pde, pte;
|
int pde, pte;
|
||||||
|
|
||||||
|
assert(kernel_may_alloc);
|
||||||
|
|
||||||
if(phys == PG_ALLOCATEME) {
|
if(phys == PG_ALLOCATEME) {
|
||||||
assert(!(vaddr % I386_PAGE_SIZE));
|
assert(!(vaddr % I386_PAGE_SIZE));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -37,6 +37,9 @@ char *video_mem = (char *) MULTIBOOT_VIDEO_BUFFER;
|
||||||
/* String length used for mb_itoa */
|
/* String length used for mb_itoa */
|
||||||
#define ITOA_BUFFER_SIZE 20
|
#define ITOA_BUFFER_SIZE 20
|
||||||
|
|
||||||
|
/* Kernel may use memory */
|
||||||
|
int kernel_may_alloc = 1;
|
||||||
|
|
||||||
static int mb_set_param(char *bigbuf, char *name, char *value, kinfo_t *cbi)
|
static int mb_set_param(char *bigbuf, char *name, char *value, kinfo_t *cbi)
|
||||||
{
|
{
|
||||||
char *p = bigbuf;
|
char *p = bigbuf;
|
||||||
|
@ -96,16 +99,6 @@ int overlaps(multiboot_module_t *mod, int n, int cmp_mod)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_memmap(kinfo_t *cbi)
|
|
||||||
{
|
|
||||||
int m;
|
|
||||||
assert(cbi->mmap_size < MAXMEMMAP);
|
|
||||||
for(m = 0; m < cbi->mmap_size; m++) {
|
|
||||||
printf("%08lx-%08lx ",cbi->memmap[m].addr, cbi->memmap[m].addr + cbi->memmap[m].len);
|
|
||||||
}
|
|
||||||
printf("\nsize %08lx\n", cbi->mmap_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void get_parameters(u32_t ebx, kinfo_t *cbi)
|
void get_parameters(u32_t ebx, kinfo_t *cbi)
|
||||||
{
|
{
|
||||||
multiboot_memory_map_t *mmap;
|
multiboot_memory_map_t *mmap;
|
||||||
|
@ -225,9 +218,6 @@ kinfo_t *pre_init(u32_t magic, u32_t ebx)
|
||||||
* Here we find out whether we should do serial output.
|
* Here we find out whether we should do serial output.
|
||||||
*/
|
*/
|
||||||
get_parameters(ebx, &kinfo);
|
get_parameters(ebx, &kinfo);
|
||||||
|
|
||||||
/* Say hello. */
|
|
||||||
printf("MINIX loading\n");
|
|
||||||
|
|
||||||
assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
|
assert(magic == MULTIBOOT_BOOTLOADER_MAGIC);
|
||||||
|
|
||||||
|
@ -236,7 +226,7 @@ kinfo_t *pre_init(u32_t magic, u32_t ebx)
|
||||||
* this code stays where it should be.
|
* this code stays where it should be.
|
||||||
*/
|
*/
|
||||||
pg_clear();
|
pg_clear();
|
||||||
pg_identity();
|
pg_identity(&kinfo);
|
||||||
kinfo.freepde_start = pg_mapkernel();
|
kinfo.freepde_start = pg_mapkernel();
|
||||||
pg_load();
|
pg_load();
|
||||||
vm_enable_paging();
|
vm_enable_paging();
|
||||||
|
|
|
@ -21,19 +21,13 @@
|
||||||
/* This is OK initially, when the 1:1 mapping is still there. */
|
/* This is OK initially, when the 1:1 mapping is still there. */
|
||||||
char *video_mem = (char *) MULTIBOOT_VIDEO_BUFFER;
|
char *video_mem = (char *) MULTIBOOT_VIDEO_BUFFER;
|
||||||
|
|
||||||
struct gatedesc_s {
|
|
||||||
u16_t offset_low;
|
|
||||||
u16_t selector;
|
|
||||||
u8_t pad; /* |000|XXXXX| ig & trpg, |XXXXXXXX| task g */
|
|
||||||
u8_t p_dpl_type; /* |P|DL|0|TYPE| */
|
|
||||||
u16_t offset_high;
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
/* Storage for gdt, idt and tss. */
|
/* Storage for gdt, idt and tss. */
|
||||||
static struct segdesc_s gdt[GDT_SIZE] __aligned(DESC_SIZE);
|
struct segdesc_s gdt[GDT_SIZE] __aligned(DESC_SIZE);
|
||||||
struct gatedesc_s idt[IDT_SIZE] __aligned(DESC_SIZE);
|
struct gatedesc_s idt[IDT_SIZE] __aligned(DESC_SIZE);
|
||||||
struct tss_s tss[CONFIG_MAX_CPUS];
|
struct tss_s tss[CONFIG_MAX_CPUS];
|
||||||
|
|
||||||
|
int prot_init_done = 0;
|
||||||
|
|
||||||
phys_bytes vir2phys(void *vir)
|
phys_bytes vir2phys(void *vir)
|
||||||
{
|
{
|
||||||
extern char _kern_vir_base, _kern_phys_base; /* in kernel.lds */
|
extern char _kern_vir_base, _kern_phys_base; /* in kernel.lds */
|
||||||
|
@ -263,12 +257,33 @@ multiboot_module_t *bootmod(int pnr)
|
||||||
panic("boot module %d not found", pnr);
|
panic("boot module %d not found", pnr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int booting_cpu = 0;
|
||||||
|
|
||||||
|
void prot_load_selectors(void)
|
||||||
|
{
|
||||||
|
/* this function is called by both prot_init by the BSP and
|
||||||
|
* the early AP booting code in mpx.S by secondary CPU's.
|
||||||
|
* everything is set up the same except for the TSS that is per-CPU.
|
||||||
|
*/
|
||||||
|
x86_lgdt(&gdt_desc); /* Load gdt */
|
||||||
|
idt_init();
|
||||||
|
idt_reload();
|
||||||
|
x86_lldt(LDT_SELECTOR); /* Load bogus ldt */
|
||||||
|
x86_ltr(TSS_SELECTOR(booting_cpu));
|
||||||
|
|
||||||
|
x86_load_kerncs();
|
||||||
|
x86_load_ds(KERN_DS_SELECTOR);
|
||||||
|
x86_load_es(KERN_DS_SELECTOR);
|
||||||
|
x86_load_fs(KERN_DS_SELECTOR);
|
||||||
|
x86_load_gs(KERN_DS_SELECTOR);
|
||||||
|
x86_load_ss(KERN_DS_SELECTOR);
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* prot_init *
|
* prot_init *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
void prot_init()
|
void prot_init()
|
||||||
{
|
{
|
||||||
int sel_tss;
|
|
||||||
extern char k_boot_stktop;
|
extern char k_boot_stktop;
|
||||||
|
|
||||||
memset(gdt, 0, sizeof(gdt));
|
memset(gdt, 0, sizeof(gdt));
|
||||||
|
@ -279,7 +294,7 @@ void prot_init()
|
||||||
gdt_desc.limit = sizeof(gdt)-1;
|
gdt_desc.limit = sizeof(gdt)-1;
|
||||||
idt_desc.base = (u32_t) idt;
|
idt_desc.base = (u32_t) idt;
|
||||||
idt_desc.limit = sizeof(idt)-1;
|
idt_desc.limit = sizeof(idt)-1;
|
||||||
sel_tss = tss_init(0, &k_boot_stktop);
|
tss_init(0, &k_boot_stktop);
|
||||||
|
|
||||||
/* Build GDT */
|
/* Build GDT */
|
||||||
init_param_dataseg(&gdt[LDT_INDEX],
|
init_param_dataseg(&gdt[LDT_INDEX],
|
||||||
|
@ -290,22 +305,11 @@ void prot_init()
|
||||||
init_codeseg(USER_CS_INDEX, USER_PRIVILEGE);
|
init_codeseg(USER_CS_INDEX, USER_PRIVILEGE);
|
||||||
init_dataseg(USER_DS_INDEX, USER_PRIVILEGE);
|
init_dataseg(USER_DS_INDEX, USER_PRIVILEGE);
|
||||||
|
|
||||||
x86_lgdt(&gdt_desc); /* Load gdt */
|
|
||||||
idt_init();
|
|
||||||
idt_reload();
|
|
||||||
x86_lldt(LDT_SELECTOR); /* Load bogus ldt */
|
|
||||||
x86_ltr(sel_tss); /* Load global TSS */
|
|
||||||
|
|
||||||
/* Currently the multiboot segments are loaded; which is fine, but
|
/* Currently the multiboot segments are loaded; which is fine, but
|
||||||
* let's replace them with the ones from our own GDT so we test
|
* let's replace them with the ones from our own GDT so we test
|
||||||
* right away whether they work as expected.
|
* right away whether they work as expected.
|
||||||
*/
|
*/
|
||||||
x86_load_kerncs();
|
prot_load_selectors();
|
||||||
x86_load_ds(KERN_DS_SELECTOR);
|
|
||||||
x86_load_es(KERN_DS_SELECTOR);
|
|
||||||
x86_load_fs(KERN_DS_SELECTOR);
|
|
||||||
x86_load_gs(KERN_DS_SELECTOR);
|
|
||||||
x86_load_ss(KERN_DS_SELECTOR);
|
|
||||||
|
|
||||||
/* Set up a new post-relocate bootstrap pagetable so that
|
/* Set up a new post-relocate bootstrap pagetable so that
|
||||||
* we can map in VM, and we no longer rely on pre-relocated
|
* we can map in VM, and we no longer rely on pre-relocated
|
||||||
|
@ -313,10 +317,11 @@ void prot_init()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pg_clear();
|
pg_clear();
|
||||||
pg_identity(); /* Still need 1:1 for lapic and video mem and such. */
|
pg_identity(&kinfo); /* Still need 1:1 for lapic and video mem and such. */
|
||||||
pg_mapkernel();
|
pg_mapkernel();
|
||||||
pg_load();
|
pg_load();
|
||||||
bootstrap_pagetable_done = 1; /* secondary CPU's can use it too */
|
|
||||||
|
prot_init_done = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void arch_post_init(void)
|
void arch_post_init(void)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <machine/asm.h>
|
#include <machine/asm.h>
|
||||||
|
#include <machine/vm.h>
|
||||||
#include "archconst.h"
|
#include "archconst.h"
|
||||||
|
|
||||||
.balign 4096
|
.balign 4096
|
||||||
|
@ -6,7 +7,7 @@
|
||||||
.code16
|
.code16
|
||||||
ENTRY(trampoline)
|
ENTRY(trampoline)
|
||||||
cli
|
cli
|
||||||
|
|
||||||
/* %cs has some value and we must use the same for data */
|
/* %cs has some value and we must use the same for data */
|
||||||
mov %cs, %ax
|
mov %cs, %ax
|
||||||
mov %ax, %ds
|
mov %ax, %ds
|
||||||
|
@ -20,13 +21,38 @@ ENTRY(trampoline)
|
||||||
orb $1, %al
|
orb $1, %al
|
||||||
mov %eax, %cr0
|
mov %eax, %cr0
|
||||||
|
|
||||||
|
/* set page table feature flags: cr4.PSE on, cr4.PGE off */
|
||||||
|
movl %cr4, %eax
|
||||||
|
orl $I386_CR4_PSE, %eax /* Turn on PSE */
|
||||||
|
andl $~I386_CR4_PGE, %eax /* Turn off PGE */
|
||||||
|
movl %eax, %cr4
|
||||||
|
|
||||||
|
/* load boot cr3 and turn PG on so CPU can see all of memory */
|
||||||
|
movl _C_LABEL(__ap_pt) - _C_LABEL(trampoline), %eax
|
||||||
|
movl %eax, %cr3
|
||||||
|
movl %cr0, %ecx
|
||||||
|
orl $I386_CR0_PG, %ecx
|
||||||
|
movl %ecx, %cr0
|
||||||
|
|
||||||
|
/* turn on cr4.PGE after cr0.PG is on */
|
||||||
|
movl %cr4, %eax
|
||||||
|
orl $I386_CR4_PGE, %eax
|
||||||
|
movl %eax, %cr4
|
||||||
|
|
||||||
|
/* jump into regular highly mapped kernel */
|
||||||
ljmpl $KERN_CS_SELECTOR, $_C_LABEL(startup_ap_32)
|
ljmpl $KERN_CS_SELECTOR, $_C_LABEL(startup_ap_32)
|
||||||
|
|
||||||
.balign 4
|
.balign 4
|
||||||
LABEL(__ap_id)
|
LABEL(__ap_id)
|
||||||
.space 4
|
.space 4
|
||||||
|
LABEL(__ap_pt)
|
||||||
|
.space 4
|
||||||
LABEL(__ap_gdt)
|
LABEL(__ap_gdt)
|
||||||
.space 8
|
.space 8
|
||||||
LABEL(__ap_idt)
|
LABEL(__ap_idt)
|
||||||
.space 8
|
.space 8
|
||||||
|
LABEL(__ap_gdt_tab)
|
||||||
|
.space GDT_SIZE*DESC_SIZE
|
||||||
|
LABEL(__ap_idt_tab)
|
||||||
|
.space IDT_SIZE*DESC_SIZE
|
||||||
LABEL(__trampoline_end)
|
LABEL(__trampoline_end)
|
||||||
|
|
|
@ -59,11 +59,11 @@ EXTERN u64_t cpu_hz[CONFIG_MAX_CPUS];
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
EXTERN int config_no_smp; /* optionaly turn off SMP */
|
EXTERN int config_no_smp; /* optionaly turn off SMP */
|
||||||
#endif
|
#endif
|
||||||
EXTERN int bootstrap_pagetable_done;
|
|
||||||
|
|
||||||
/* VM */
|
/* VM */
|
||||||
EXTERN int vm_running;
|
EXTERN int vm_running;
|
||||||
EXTERN int catch_pagefaults;
|
EXTERN int catch_pagefaults;
|
||||||
|
EXTERN int kernel_may_alloc;
|
||||||
|
|
||||||
/* Variables that are initialized elsewhere are just extern here. */
|
/* Variables that are initialized elsewhere are just extern here. */
|
||||||
extern struct boot_image image[NR_BOOT_PROCS]; /* system image processes */
|
extern struct boot_image image[NR_BOOT_PROCS]; /* system image processes */
|
||||||
|
|
|
@ -107,6 +107,9 @@ void bsp_finish_booting(void)
|
||||||
machine.bsp_id = 0;
|
machine.bsp_id = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Kernel may no longer use bits of memory as VM will be running soon */
|
||||||
|
kernel_may_alloc = 0;
|
||||||
|
|
||||||
switch_to_user();
|
switch_to_user();
|
||||||
NOT_REACHABLE;
|
NOT_REACHABLE;
|
||||||
}
|
}
|
||||||
|
@ -128,6 +131,9 @@ void kmain(kinfo_t *local_cbi)
|
||||||
/* We can talk now */
|
/* We can talk now */
|
||||||
printf("MINIX booting\n");
|
printf("MINIX booting\n");
|
||||||
|
|
||||||
|
/* Kernel may use bits of main memory before VM is started */
|
||||||
|
kernel_may_alloc = 1;
|
||||||
|
|
||||||
assert(sizeof(kinfo.boot_procs) == sizeof(image));
|
assert(sizeof(kinfo.boot_procs) == sizeof(image));
|
||||||
memcpy(kinfo.boot_procs, image, sizeof(kinfo.boot_procs));
|
memcpy(kinfo.boot_procs, image, sizeof(kinfo.boot_procs));
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue