- minor changes to support APIC

(currently, we got page fault by entering apic_calibration)
- first steps to realize a loader



git-svn-id: http://svn.lfbs.rwth-aachen.de/svn/scc/trunk/MetalSVM@365 315a16e6-25f9-4109-90ae-ca3045a26c18
This commit is contained in:
stefan 2011-01-05 10:16:53 +00:00
parent 81d0b19726
commit 8646b56a63
9 changed files with 162 additions and 97 deletions

View file

@ -105,4 +105,9 @@ int arch_paging_init(void);
*/
int get_kernel_pgd(task_t* task);
/*
* Create a new page directory for a new user-level task
*/
page_dir_t* create_pgd(void);
#endif

View file

@ -139,7 +139,7 @@ inline static int system_init(void)
scc_init();
#endif
gdt_install();
//apic_init();
apic_init();
#ifdef CONFIG_PCI
pci_init();
#endif

View file

@ -19,6 +19,7 @@
#include <metalsvm/stddef.h>
#include <metalsvm/stdio.h>
#include <metalsvm/stdlib.h>
#include <metalsvm/string.h>
#include <metalsvm/errno.h>
#include <metalsvm/processor.h>
@ -54,7 +55,7 @@ static volatile ioapic_t* ioapic = NULL;
static uint32_t ncores = 1;
static uint8_t irq_redirect[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF};
#if MAX_CORES > 1
static uint8_t boot_code[] = {0xE9, 0x1F, 0x00, 0x90, 0x17, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00, 0x0F, 0x01, 0x16, 0x04, 0x00, 0x0F, 0x20, 0xC0, 0x0C, 0x01, 0x0F, 0x22, 0xC0, 0x66, 0xEA, 0x37, 0x00, 0x01, 0x00, 0x08, 0x00, 0x31, 0xC0, 0x66, 0xB8, 0x10, 0x00, 0x8E, 0xD8, 0x8E, 0xC0, 0x8E, 0xE0, 0x8E, 0xE8, 0x8E, 0xD0, 0xB8, 0x02, 0xD0, 0xBA, 0x02, 0x31, 0xDB, 0xEA, 0x00, 0x10, 0x10, 0x00, 0x08, 0x00};
static uint8_t boot_code[] = {0xE9, 0x1E, 0x00, 0x17, 0x00, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00, 0x0F, 0x01, 0x16, 0x03, 0x00, 0x0F, 0x20, 0xC0, 0x0C, 0x01, 0x0F, 0x22, 0xC0, 0x66, 0xEA, 0x36, 0x00, 0x01, 0x00, 0x08, 0x00, 0xFA, 0x31, 0xC0, 0x66, 0xB8, 0x10, 0x00, 0x8E, 0xD8, 0x8E, 0xC0, 0x8E, 0xE0, 0x8E, 0xE8, 0x8E, 0xD0, 0x0F, 0x20, 0xC0, 0x25, 0xFF, 0xFF, 0xFF, 0x9F, 0x0D, 0x20, 0x00, 0x00, 0x00, 0x0F, 0x22, 0xC0, 0x31, 0xC0, 0x0F, 0x22, 0xD8, 0xBC, 0xEF, 0xBE, 0xAD, 0xDE, 0x31, 0xC0, 0x31, 0xDB, 0xEA, 0xDE, 0xC0, 0xAD, 0xDE, 0x08, 0x00};
#endif
static uint8_t initialized = 0;
static atomic_int32_t cpu_online = ATOMIC_INIT(1);
@ -68,10 +69,10 @@ static inline uint32_t lapic_read(uint32_t addr)
static inline void lapic_write(uint32_t addr, uint32_t value)
{
/*
* to avoid ap entium bug, we have to read a apic register before
* before we write value to this register
* to avoid a pentium bug, we have to read a apic register
* before we write a value to this register
*/
asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(addr+lapic), "b"(value) : "%edx");
asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(lapic+addr), "b"(value) : "%edx");
//*((volatile uint32_t*) (lapic+addr)) = value;
}
@ -167,20 +168,16 @@ static int wakeup_all_aps(uint32_t start_eip)
}
#endif
int smp_main(void)
{
#if MAX_CORES > 1
static void smp_main(void)
{
vga_puts("JJAJAJAJAJAJA\n");
lowlevel_init();
atomic_int32_inc(&cpu_online);
kputs("JAJAJAJ\n");
while(1)
;
#endif
return 0;
while(1) ;
}
#endif
#ifndef CONFIG_MULTIBOOT
static unsigned int* search_apic(unsigned int base, unsigned int limit) {
@ -201,6 +198,7 @@ static unsigned int* search_apic(unsigned int base, unsigned int limit) {
int smp_init(void)
{
uint32_t i;
size_t bootaddr;
int err;
if (ncores <= 1)
@ -210,12 +208,19 @@ int smp_init(void)
* dirty hack: Copy 16bit startup code (see tools/smp_setup.asm)
* to a 16bit address. Wakeup the other cores via IPI. They start
* at this address in real mode, switch to protected and finally
* they jump to 0x101000 (see smp_start in entry.asm)
* they jump to smp_main.
*/
memcpy((void*)0x10000, boot_code, sizeof(boot_code));
bootaddr = 0x10000;
map_region(per_core(current_task), bootaddr, get_pages(1), 1, MAP_KERNEL_SPACE);
for(i=0; i<sizeof(boot_code); i+=sizeof(size_t))
{
// replace 0xDEADC0DE with the address of the smp entry code
if (*((size_t*) (bootaddr+i)) == 0xDEADC0DE)
*((size_t*) (bootaddr+i)) = (size_t) smp_main;
}
kprintf("size of the boot_code %d\n", sizeof(boot_code));
err = wakeup_all_aps(0x10000);
err = wakeup_all_aps(bootaddr);
if (err)
kprintf("Unable to wakeup application processors: %d\n", err);
@ -461,7 +466,7 @@ check_lapic:
goto out;
}
//return 0;
return 0;
out:
apic_mp = NULL;

View file

@ -95,7 +95,7 @@ size_t virt_to_phys(task_t* task, size_t viraddr)
if (!(task->pgd->entries[index1] & 0xFFFFF000))
goto out;
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*4) & 0xFFFFF000);
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*PAGE_SIZE) & 0xFFFFF000);
if (!pgt || !(pgt->entries[index2]))
goto out;
@ -167,14 +167,14 @@ size_t map_region(task_t* task, size_t viraddr, size_t phyaddr, uint32_t npages,
// clear the page table
if (paging_enabled)
memset((void*) (KERNEL_SPACE - 1024*PAGE_SIZE + index*4), 0, PAGE_SIZE);
memset((void*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index*PAGE_SIZE) & 0xFFFFF000), 0, PAGE_SIZE);
else
memset(pgt, 0, PAGE_SIZE);
} else pgt = (page_table_t*) (task->pgd->entries[index] & 0xFFFFF000);
/* convert physical address to virtual */
if (paging_enabled)
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index*4) & 0xFFFFF000);
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index*PAGE_SIZE) & 0xFFFFF000);
index = (viraddr >> 12) & 0x3FF;
if (BUILTIN_EXPECT(pgt->entries[index], 0)) {
@ -225,7 +225,7 @@ size_t vm_alloc(task_t* task, uint32_t npages, uint32_t flags)
index1 = i >> 22;
index2 = (i >> 12) & 0x3FF;
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*4) & 0xFFFFF000);
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*PAGE_SIZE) & 0xFFFFF000);
if (!pgt || !(pgt->entries[index2])) {
i+=PAGE_SIZE;
j++;
@ -257,7 +257,7 @@ int vm_free(task_t* task, size_t viraddr, uint32_t npages)
index1 = viraddr >> 22;
index2 = (viraddr >> 12) & 0x3FF;
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*4) & 0xFFFFF000);
pgt = (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + index1*PAGE_SIZE) & 0xFFFFF000);
if (!pgt)
continue;
pgt->entries[index2] = 0;
@ -289,7 +289,7 @@ int print_paging_tree(size_t viraddr)
/* convert physical address to virtual */
if (paging_enabled && pgt)
pgt = (page_table_t*) (KERNEL_SPACE - 1024*PAGE_SIZE + index1*4);
pgt = (page_table_t*) (KERNEL_SPACE - 1024*PAGE_SIZE + index1*PAGE_SIZE);
kprintf("\tPage table entry %u: ", index2);
if (pgt)

View file

@ -29,59 +29,92 @@ extern "C" {
#define ELF_MAGIC 0x464C457F
#define ELF_ET_NONE 0x0000 // no type
#define ELF_ET_REL 0x0001 // relocatable
#define ELF_ET_EXEC 0x0002 // executeable
#define ELF_ET_DYN 0x0003 // Shared-Object-File
#define ELF_ET_CORE 0x0004 // Corefile
#define ELF_ET_LOPROC 0xFF00 // Processor-specific
#define ELF_ET_HIPROC 0x00FF // Processor-specific
#define ELF_EM_NONE 0x0000 // no type
#define ELF_EM_M32 0x0001 // AT&T WE 32100
#define ELF_EM_SPARC 0x0002 // SPARC
#define ELF_EM_386 0x0003 // Intel 80386
#define ELF_EM_68K 0x0004 // Motorola 68000
#define ELF_EM_88K 0x0005 // Motorola 88000
#define ELF_EM_860 0x0007 // Intel 80860
#define ELF_EM_MIPS 0x0008 // MIPS RS3000
#define ELF_CLASS_NONE 0x0000
#define ELF_CLASS_32 0x0001 // 32bit file
#define ELF_CLASS_64 0x0002 // 64bit file
#define ELF_DATA_NONE 0x0000
#define ELF_DATA_2LSB 0x0001
#define ELF_DATA_2MSB 0x002
/* Legal values for p_type (segment type). */
#define PT_NULL 0 /* Program header table entry unused */
#define PT_LOAD 1 /* Loadable program segment */
#define PT_DYNAMIC 2 /* Dynamic linking information */
#define PT_INTERP 3 /* Program interpreter */
#define PT_NOTE 4 /* Auxiliary information */
#define PT_SHLIB 5
#define PT_PHDR 6 /* Entry for header table itself */
#define PT_TLS 7 /* Thread-local storage segment */
#define PT_NUM 8 /* Number of defined types */
#define PT_LOOS 0x60000000 /* Start of OS-specific */
#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
#define PT_LOSUNW 0x6ffffffa
#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
#define PT_HISUNW 0x6fffffff
#define PT_HIOS 0x6fffffff /* End of OS-specific */
#define PT_LOPROC 0x70000000 /* Start of processor-specific */
#define PT_HIPROC 0x7fffffff /* End of processor-specific */
#define ELF_PT_NULL 0 /* Program header table entry unused */
#define ELF_PT_LOAD 1 /* Loadable program segment */
#define ELF_PT_DYNAMIC 2 /* Dynamic linking information */
#define ELF_PT_INTERP 3 /* Program interpreter */
#define ELF_PT_NOTE 4 /* Auxiliary information */
#define ELF_PT_SHLIB 5
#define ELF_PT_PHDR 6 /* Entry for header table itself */
#define ELF_PT_TLS 7 /* Thread-local storage segment */
#define ELF_PT_NUM 8 /* Number of defined types */
#define ELF_PT_LOOS 0x60000000 /* Start of OS-specific */
#define ELF_PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
#define ELF_PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
#define ELF_PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
#define ELF_PT_LOSUNW 0x6ffffffa
#define ELF_PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
#define ELF_PT_SUNWSTACK 0x6ffffffb /* Stack segment */
#define ELF_PT_HISUNW 0x6fffffff
#define ELF_PT_HIOS 0x6fffffff /* End of OS-specific */
#define ELF_PT_LOPROC 0x70000000 /* Start of processor-specific */
#define ELF_PT_HIPROC 0x7fffffff /* End of processor-specific */
typedef struct {
uint32_t magic;
uint32_t version;
uint64_t reserved;
uint64_t version2;
uint32_t entry;
uint32_t ph_offset;
uint32_t sh_offset;
uint32_t flags;
uint16_t header_size;
uint16_t ph_entry_size;
uint16_t ph_entry_count;
uint16_t sh_entry_size;
uint16_t sh_entry_count;
uint16_t sh_str_table_index;
} __attribute__((packed)) elf_header_t;
uint32_t magic;
uint8_t _class;
uint8_t data;
uint8_t version;
uint8_t pad[8];
uint8_t nident;
} __attribute__ ((packed)) elf_ident_t;
typedef struct {
uint32_t type;
uint32_t offset;
uint32_t virt_addr;
uint32_t phys_addr;
uint32_t file_size;
uint32_t mem_size;
uint32_t flags;
uint32_t alignment;
} __attribute__((packed)) elf_program_header_t;
elf_ident_t ident;
uint16_t type;
uint16_t machine;
uint32_t version;
uint32_t entry;
uint32_t ph_offset;
uint32_t sh_offset;
uint32_t flags;
uint16_t header_size;
uint16_t ph_entry_size;
uint16_t ph_entry_count;
uint16_t sh_entry_size;
uint16_t sh_entry_count;
uint16_t sh_str_table_index;
} __attribute__ ((packed)) elf_header_t;
typedef struct {
uint32_t type;
uint32_t offset;
uint32_t virt_addr;
uint32_t phys_addr;
uint32_t file_size;
uint32_t mem_size;
uint32_t flags;
uint32_t alignment;
} __attribute__ ((packed)) elf_program_header_t;
#ifdef __cplusplus
}
#endif
#endif

View file

@ -38,7 +38,7 @@ int multitasking_init(void);
int create_kernel_task(tid_t*, entry_point_t, void*);
/* create a user level task. if sz is zero, the task with the default stack size will be created */
int create_user_task(tid_t* id, entry_point_t ep, void* arg, size_t sz);
int create_user_task(tid_t* id, size_t sz, const char* filename, int argc, char** argv);
/* until the task id is runnint, the current task is block */
int join_task(tid_t id, int* result);

View file

@ -97,7 +97,7 @@ int main(void)
kprintf("Kernel starts at %p and ends at %p\n", &kernel_start, &kernel_end);
system_calibration();
network_init();
//network_init();
kprintf("Processor frequency: %u MHz\n", get_cpu_frequency());
kprintf("Total memory: %u MBytes\n", atomic_int32_read(&total_pages)/((1024*1024)/PAGE_SIZE));
@ -105,7 +105,7 @@ int main(void)
kprintf("Current available memory: %u MBytes\n", atomic_int32_read(&total_available_pages)/((1024*1024)/PAGE_SIZE));
sleep(5);
list_root();
//list_root();
test_init();
per_core(current_task)->status = TASK_IDLE;

View file

@ -28,6 +28,8 @@
#include <metalsvm/spinlock.h>
#include <metalsvm/mailbox.h>
#include <metalsvm/syscall.h>
#include <metalsvm/fs.h>
#include <metalsvm/elf.h>
DEFINE_PER_CORE(task_t*, current_task, NULL);
static task_t task_table[MAX_TASKS] = {[0 ... MAX_TASKS-1] = {0, TASK_INVALID, NULL, 0, ATOMIC_INIT(0), NULL, NULL}};
@ -173,10 +175,48 @@ int create_kernel_task(tid_t* id, entry_point_t ep, void* arg)
return create_task(id, ep, arg, 0, 0);
}
int create_user_task(tid_t* id, entry_point_t ep, void* arg, size_t stack_size)
int create_user_task(tid_t* id, size_t sz, const char* filename, int argc, char** argv)
{
vfs_node_t* node;
elf_header_t header;
page_dir_t* pgd;
node = findnode_fs(filename);
if (node && (node->type == FS_FILE)) {
kprintf("Found application %s at node %p\n", filename, node);
read_fs(node, (uint8_t*)&header, sizeof(elf_header_t), 0);
if (BUILTIN_EXPECT(header.ident.magic != ELF_MAGIC, 0))
return -EINVAL;
if (BUILTIN_EXPECT(header.type != ELF_ET_EXEC, 0))
return -EINVAL;
if (BUILTIN_EXPECT(header.machine != ELF_EM_386, 0))
return -EINVAL;
if (BUILTIN_EXPECT(header.ident._class != ELF_CLASS_32, 0))
return -EINVAL;
if (BUILTIN_EXPECT(header.ident.data != ELF_DATA_2LSB, 0))
return -EINVAL;
kprintf("entry point at 0x%x\n", header.entry);
pgd = create_pgd();
if (!pgd)
return -ENOMEM;
return 0;
}
return -EINVAL;
}
/*int create_user_task(tid_t* id, entry_point_t ep, void* arg, size_t stack_size)
{
return create_task(id, ep, arg, stack_size, 1);
}
}*/
int join_task(tid_t id, int* result)
{

View file

@ -83,25 +83,6 @@ static int STDCALL foo(void* arg)
return 42;
}
static int STDCALL userfoo(void* arg)
{
int i;
if (!arg)
return 0;
for (i = 0; i < 5; i++)
SYSCALL3(__NR_write, 0, (char*)arg, strlen((char*)arg));
// demo of a general protection fault
//kprintf("test user\n");
/* task exit */
SYSCALL1(__NR_exit, 0);
return 0;
}
static int STDCALL join_test(void* arg)
{
tid_t id;
@ -118,16 +99,17 @@ static int STDCALL join_test(void* arg)
int test_init(void)
{
tid_t id1, id2, id3, id4, id5;
char* argv[1] = {"/bin/hello"};
sem_init(&producing, 1);
sem_init(&consuming, 0);
mailbox_int32_init(&mbox);
create_kernel_task(&id1, foo, "Hello from foo1\n");
//create_kernel_task(&id1, foo, "Hello from foo1\n");
//create_kernel_task(&id2, join_test, NULL);
create_kernel_task(&id3, producer, NULL);
create_kernel_task(&id4, consumer, NULL);
//create_user_task(&id5, userfoo, "Hello from user process foo\n", 0);
//create_kernel_task(&id3, producer, NULL);
//create_kernel_task(&id4, consumer, NULL);
create_user_task(&id5, 8192, "/bin/hello", 1, argv);
return 0;
}