_start() now uses set_segment_descriptor() to initialize the GDT instead of

the direct values.
Some cleanups.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2369 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2003-01-06 08:33:59 +00:00
parent 39c5004d20
commit f143877df9
2 changed files with 75 additions and 41 deletions
+58 -27
View File
@@ -2,6 +2,8 @@
** Copyright 2001, Travis Geiselbrecht. All rights reserved. ** Copyright 2001, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License. ** Distributed under the terms of the NewOS License.
*/ */
#include <stage2.h> #include <stage2.h>
#include <arch/x86/stage2_priv.h> #include <arch/x86/stage2_priv.h>
@@ -18,13 +20,15 @@ static unsigned int kernel_entry_point = 0;
static int smp_get_current_cpu(kernel_args *ka); static int smp_get_current_cpu(kernel_args *ka);
static unsigned int map_page(kernel_args *ka, unsigned int paddr, unsigned int vaddr)
static unsigned int
map_page(kernel_args *ka, unsigned int paddr, unsigned int vaddr)
{ {
unsigned int *pentry; unsigned int *pentry;
unsigned int *pgdir = (unsigned int *)(ka->arch_args.page_hole + (4*1024*1024-PAGE_SIZE)); unsigned int *pgdir = (unsigned int *)(ka->arch_args.page_hole + (4*1024*1024-PAGE_SIZE));
// check to see if a page table exists for this range // check to see if a page table exists for this range
if(pgdir[vaddr / PAGE_SIZE / 1024] == 0) { if (pgdir[vaddr / PAGE_SIZE / 1024] == 0) {
unsigned int pgtable; unsigned int pgtable;
// we need to allocate a pgtable // we need to allocate a pgtable
pgtable = ka->phys_alloc_range[0].start + ka->phys_alloc_range[0].size; pgtable = ka->phys_alloc_range[0].start + ka->phys_alloc_range[0].size;
@@ -47,28 +51,37 @@ static unsigned int map_page(kernel_args *ka, unsigned int paddr, unsigned int v
return 0; return 0;
} }
static unsigned int apic_read(unsigned int *addr)
static unsigned int
apic_read(unsigned int *addr)
{ {
return *addr; return *addr;
} }
static void apic_write(unsigned int *addr, unsigned int data)
static void
apic_write(unsigned int *addr, unsigned int data)
{ {
*addr = data; *addr = data;
} }
/* /*
static void *mp_virt_to_phys(void *ptr) static void *
mp_virt_to_phys(void *ptr)
{ {
return ((void *)(((unsigned int)ptr - mp_mem_virt) + mp_mem_phys)); return ((void *)(((unsigned int)ptr - mp_mem_virt) + mp_mem_phys));
} }
*/ */
static void *mp_phys_to_virt(void *ptr)
static void *
mp_phys_to_virt(void *ptr)
{ {
return ((void *)(((unsigned int)ptr - mp_mem_phys) + mp_mem_virt)); return ((void *)(((unsigned int)ptr - mp_mem_phys) + mp_mem_virt));
} }
static unsigned int *smp_probe(unsigned int base, unsigned int limit)
static unsigned int *
smp_probe(unsigned int base, unsigned int limit)
{ {
unsigned int *ptr; unsigned int *ptr;
@@ -83,7 +96,9 @@ static unsigned int *smp_probe(unsigned int base, unsigned int limit)
return NULL; return NULL;
} }
static void smp_do_config(kernel_args *ka)
static void
smp_do_config(kernel_args *ka)
{ {
char *ptr; char *ptr;
int i; int i;
@@ -168,6 +183,7 @@ static void smp_do_config(kernel_args *ka)
} }
} }
struct smp_scan_spots_struct { struct smp_scan_spots_struct {
unsigned int start; unsigned int start;
unsigned int stop; unsigned int stop;
@@ -180,21 +196,23 @@ static struct smp_scan_spots_struct smp_scan_spots[] = {
{ 0, 0, 0 } { 0, 0, 0 }
}; };
static int smp_find_mp_config(kernel_args *ka)
static int
smp_find_mp_config(kernel_args *ka)
{ {
int i; int i;
// XXX for now, assume the memory is identity mapped by the 1st stage // XXX for now, assume the memory is identity mapped by the 1st stage
for(i=0; smp_scan_spots[i].len > 0; i++) { for (i = 0; smp_scan_spots[i].len > 0; i++) {
mp_flt_ptr = (struct mp_flt_struct *)smp_probe(smp_scan_spots[i].start, mp_flt_ptr = (struct mp_flt_struct *)smp_probe(smp_scan_spots[i].start,
smp_scan_spots[i].stop); smp_scan_spots[i].stop);
if(mp_flt_ptr != NULL) if(mp_flt_ptr != NULL)
break; break;
} }
#if NO_SMP #if NO_SMP
if(0) { if (0) {
#else #else
if(mp_flt_ptr != NULL) { if (mp_flt_ptr != NULL) {
#endif #endif
mp_mem_phys = smp_scan_spots[i].start; mp_mem_phys = smp_scan_spots[i].start;
mp_mem_virt = smp_scan_spots[i].start; mp_mem_virt = smp_scan_spots[i].start;
@@ -231,7 +249,9 @@ static int smp_find_mp_config(kernel_args *ka)
} }
} }
static int smp_setup_apic(kernel_args *ka)
static int
smp_setup_apic(kernel_args *ka)
{ {
unsigned int config; unsigned int config;
// dprintf("setting up the apic..."); // dprintf("setting up the apic...");
@@ -278,12 +298,15 @@ static int smp_setup_apic(kernel_args *ka)
return 0; return 0;
} }
// target function of the trampoline code // target function of the trampoline code
// The trampoline code should have the pgdir and a gdt set up for us, // The trampoline code should have the pgdir and a gdt set up for us,
// along with us being on the final stack for this processor. We need // along with us being on the final stack for this processor. We need
// to set up the local APIC and load the global idt and gdt. When we're // to set up the local APIC and load the global idt and gdt. When we're
// done, we'll jump into the kernel with the cpu number as an argument. // done, we'll jump into the kernel with the cpu number as an argument.
static int smp_cpu_ready(void)
static int
smp_cpu_ready(void)
{ {
kernel_args *ka = saved_ka; kernel_args *ka = saved_ka;
unsigned int curr_cpu = smp_get_current_cpu(ka); unsigned int curr_cpu = smp_get_current_cpu(ka);
@@ -324,7 +347,9 @@ static int smp_cpu_ready(void)
return 0; return 0;
} }
static int smp_boot_all_cpus(kernel_args *ka)
static int
smp_boot_all_cpus(kernel_args *ka)
{ {
unsigned int trampoline_code; unsigned int trampoline_code;
unsigned int trampoline_stack; unsigned int trampoline_stack;
@@ -345,7 +370,7 @@ static int smp_boot_all_cpus(kernel_args *ka)
(unsigned int)&smp_trampoline_end - (unsigned int)&smp_trampoline); (unsigned int)&smp_trampoline_end - (unsigned int)&smp_trampoline);
// boot the cpus // boot the cpus
for(i = 1; i < ka->num_cpus; i++) { for (i = 1; i < ka->num_cpus; i++) {
unsigned int *final_stack; unsigned int *final_stack;
unsigned int *final_stack_ptr; unsigned int *final_stack_ptr;
unsigned int *tramp_stack_ptr; unsigned int *tramp_stack_ptr;
@@ -387,7 +412,7 @@ static int smp_boot_all_cpus(kernel_args *ka)
memcpy(&((unsigned int *)trampoline_stack)[2], (void *)ka->arch_args.vir_gdt, 6*4); memcpy(&((unsigned int *)trampoline_stack)[2], (void *)ka->arch_args.vir_gdt, 6*4);
/* clear apic errors */ /* clear apic errors */
if(ka->arch_args.cpu_apic_version[i] & 0xf0) { if (ka->arch_args.cpu_apic_version[i] & 0xf0) {
apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0);
apic_read(APIC_ESR); apic_read(APIC_ESR);
} }
@@ -399,7 +424,7 @@ static int smp_boot_all_cpus(kernel_args *ka)
apic_write(APIC_ICR1, config); apic_write(APIC_ICR1, config);
// wait for pending to end // wait for pending to end
while((apic_read(APIC_ICR1) & 0x00001000) == 0x00001000); while ((apic_read(APIC_ICR1) & 0x00001000) == 0x00001000);
/* deassert INIT */ /* deassert INIT */
config = (apic_read(APIC_ICR2) & 0x00ffffff) | (ka->arch_args.cpu_apic_id[i] << 24); config = (apic_read(APIC_ICR2) & 0x00ffffff) | (ka->arch_args.cpu_apic_id[i] << 24);
@@ -407,7 +432,7 @@ static int smp_boot_all_cpus(kernel_args *ka)
config = (apic_read(APIC_ICR1) & 0xfff00000) | 0x00008500; config = (apic_read(APIC_ICR1) & 0xfff00000) | 0x00008500;
// wait for pending to end // wait for pending to end
while((apic_read(APIC_ICR1) & 0x00001000) == 0x00001000); while ((apic_read(APIC_ICR1) & 0x00001000) == 0x00001000);
// dprintf("0x%x\n", apic_read(APIC_ICR1)); // dprintf("0x%x\n", apic_read(APIC_ICR1));
/* wait 10ms */ /* wait 10ms */
@@ -431,14 +456,16 @@ static int smp_boot_all_cpus(kernel_args *ka)
/* wait */ /* wait */
sleep(200); sleep(200);
while((apic_read(APIC_ICR1)& 0x00001000) == 0x00001000); while ((apic_read(APIC_ICR1)& 0x00001000) == 0x00001000);
} }
} }
return 0; return 0;
} }
static void calculate_apic_timer_conversion_factor(kernel_args *ka)
static void
calculate_apic_timer_conversion_factor(kernel_args *ka)
{ {
long long t1, t2; long long t1, t2;
unsigned int config; unsigned int config;
@@ -467,14 +494,16 @@ static void calculate_apic_timer_conversion_factor(kernel_args *ka)
dprintf("APIC ticks/sec = %d\n", ka->arch_args.apic_time_cv_factor); dprintf("APIC ticks/sec = %d\n", ka->arch_args.apic_time_cv_factor);
} }
int smp_boot(kernel_args *ka, unsigned int kernel_entry)
int
smp_boot(kernel_args *ka, unsigned int kernel_entry)
{ {
// dprintf("smp_boot: entry\n"); // dprintf("smp_boot: entry\n");
kernel_entry_point = kernel_entry; kernel_entry_point = kernel_entry;
saved_ka = ka; saved_ka = ka;
if(smp_find_mp_config(ka) > 1) { if (smp_find_mp_config(ka) > 1) {
// dprintf("smp_boot: had found > 1 cpus\n"); // dprintf("smp_boot: had found > 1 cpus\n");
// dprintf("post config:\n"); // dprintf("post config:\n");
// dprintf("num_cpus = 0x%p\n", ka->num_cpus); // dprintf("num_cpus = 0x%p\n", ka->num_cpus);
@@ -509,10 +538,12 @@ int smp_boot(kernel_args *ka, unsigned int kernel_entry)
return 0; return 0;
} }
static int smp_get_current_cpu(kernel_args *ka)
static int
smp_get_current_cpu(kernel_args *ka)
{ {
if(ka->arch_args.apic == NULL) if (ka->arch_args.apic == NULL)
return 0; return 0;
else
return ka->arch_args.cpu_os_id[(apic_read(APIC_ID) & 0xffffffff) >> 24]; return ka->arch_args.cpu_os_id[(apic_read(APIC_ID) & 0xffffffff) >> 24];
} }
+17 -14
View File
@@ -6,6 +6,7 @@
#include <bootdir.h> #include <bootdir.h>
#include <stage2.h> #include <stage2.h>
#include "arch/x86/stage2_priv.h" #include "arch/x86/stage2_priv.h"
#include "arch/x86/descriptors.h"
#include "vesa.h" #include "vesa.h"
#include <string.h> #include <string.h>
@@ -69,7 +70,7 @@ void
_start(unsigned int mem, int in_vesa, unsigned int vesa_ptr) _start(unsigned int mem, int in_vesa, unsigned int vesa_ptr)
{ {
unsigned int *idt; unsigned int *idt;
unsigned int *gdt; segment_descriptor *gdt;
unsigned int next_vaddr; unsigned int next_vaddr;
unsigned int next_paddr; unsigned int next_paddr;
unsigned int i; unsigned int i;
@@ -186,24 +187,26 @@ _start(unsigned int mem, int in_vesa, unsigned int vesa_ptr)
struct gdt_idt_descr gdt_descr; struct gdt_idt_descr gdt_descr;
// find a new gdt // find a new gdt
gdt = (unsigned int *)next_paddr; gdt = (segment_descriptor *)next_paddr;
ka->arch_args.phys_gdt = (unsigned int)gdt; ka->arch_args.phys_gdt = (unsigned int)gdt;
next_paddr += PAGE_SIZE; next_paddr += PAGE_SIZE;
MESSAGE(("gdt at ", (unsigned int)gdt, "\n")); MESSAGE(("gdt at ", (unsigned int)gdt, "\n"));
// put segment descriptors in it // put standard segment descriptors in it
gdt[0] = 0; clear_segment_descriptor(&gdt[0]);
gdt[1] = 0; set_segment_descriptor(&gdt[1], 0, 0xfffff, DT_CODE_READABLE, DPL_KERNEL);
gdt[2] = 0x0000ffff; // seg 0x8 -- kernel 4GB code // seg 0x10 - kernel 4GB code
gdt[3] = 0x00cf9a00; set_segment_descriptor(&gdt[2], 0, 0xfffff, DT_DATA_WRITEABLE, DPL_KERNEL);
gdt[4] = 0x0000ffff; // seg 0x10 -- kernel 4GB data // seg 0x10 - kernel 4GB data
gdt[5] = 0x00cf9200;
gdt[6] = 0x0000ffff; // seg 0x1b -- ring 3 4GB code set_segment_descriptor(&gdt[3], 0, 0xfffff, DT_CODE_READABLE, DPL_USER);
gdt[7] = 0x00cffa00; // seg 0x1b - ring 3 user 4GB code
gdt[8] = 0x0000ffff; // seg 0x23 -- ring 3 4GB data set_segment_descriptor(&gdt[4], 0, 0xfffff, DT_DATA_WRITEABLE, DPL_USER);
gdt[9] = 0x00cff200; // seg 0x23 - ring 3 user 4GB data
// gdt[10] & gdt[11] will be filled later by the kernel
// gdt[5] and above will be filled later by the kernel
// to contain the TSS descriptors, and for TLS (one for every CPU)
// map the gdt into virtual space // map the gdt into virtual space
mmu_map_page(next_vaddr, (unsigned int)gdt); mmu_map_page(next_vaddr, (unsigned int)gdt);