Merge branch 'master' of git.lfbs.rwth-aachen.de:metalsvm into doxygen
Conflicts: .gitignore arch/x86/include/asm/apic.h arch/x86/include/asm/page.h arch/x86/include/asm/processor.h arch/x86/kernel/idt.c
This commit is contained in:
commit
b5908af744
25 changed files with 427 additions and 228 deletions
|
@ -49,7 +49,7 @@ extern "C" {
|
|||
/// LVT LINT0 Register
|
||||
#define APIC_LINT0 0x0350
|
||||
/// LVT LINT1 Register
|
||||
#define APIC_LINT1 0x0360
|
||||
#define APIC_LINT1 0x0360
|
||||
/// LVT Error Register
|
||||
#define APIC_LVT_ER 0x0370
|
||||
/// Initial Count Register
|
||||
|
|
|
@ -53,7 +53,9 @@ inline static void irq_disable(void) {
|
|||
inline static uint32_t irq_nested_disable(void) {
|
||||
uint32_t flags;
|
||||
asm volatile("pushf; cli; popl %0": "=r"(flags) : : "memory");
|
||||
return flags;
|
||||
if (flags & (1 << 9))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Enable IRQs */
|
||||
|
@ -69,7 +71,8 @@ inline static void irq_enable(void) {
|
|||
* @param flags Flags to set. Could be the old ones you got from irq_nested_disable.
|
||||
*/
|
||||
inline static void irq_nested_enable(uint32_t flags) {
|
||||
asm volatile("pushl %0; popf" : : "r"(flags) : "memory");
|
||||
if (flags)
|
||||
irq_enable();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -60,6 +60,8 @@
|
|||
#define PG_DIRTY (1 << _PAGE_BIT_DIRTY)
|
||||
/// Big page: 4MB (or 2MB)
|
||||
#define PG_PSE (1 << _PAGE_BIT_PSE)
|
||||
/// Page is part of the MPB (SCC specific entry)
|
||||
#define PG_MPE PG_PSE
|
||||
/// Global TLB entry (Pentium Pro and later)
|
||||
#define PG_GLOBAL (1 << _PAGE_BIT_GLOBAL)
|
||||
/// This virtual address range is reserved as marked
|
||||
|
|
|
@ -40,21 +40,14 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
/*#define SCC_PMEM_REGIONS 2
|
||||
|
||||
typedef struct {
|
||||
uint32_t low;
|
||||
uint32_t high;
|
||||
} mem_region_t;
|
||||
uint32_t addr; // address of the initrd
|
||||
uint32_t size; // size of the initrd
|
||||
int32_t argc; // number of RCCE arguments
|
||||
char** argv; // RCCE arguments
|
||||
} bootinfo_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t pid;
|
||||
uint32_t tile_frequency; // in MHz
|
||||
uint32_t router_frequency; // in MHz
|
||||
mem_region_t private_mem[SCC_PMEM_REGIONS];
|
||||
} scc_info_t;
|
||||
|
||||
extern scc_info_t scc_info;*/
|
||||
extern bootinfo_t* bootinfo;
|
||||
|
||||
int scc_init(void);
|
||||
#endif
|
||||
|
@ -135,6 +128,7 @@ inline static void cpuid(uint32_t code, uint32_t* a, uint32_t* b, uint32_t* c, u
|
|||
asm volatile ("cpuid" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "0"(code));
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
/** @brief Flush the pipeline
|
||||
*
|
||||
* The cpuid-instruction is used to flush the pipeline.
|
||||
|
@ -155,6 +149,8 @@ inline static void flush_pipeline(void) {
|
|||
* @param msr The parameter which rdmsr assumes in ECX
|
||||
* @return The value rdmsr put into EDX:EAX
|
||||
*/
|
||||
=======
|
||||
>>>>>>> a9ce93d119c2709a766c19b9cfa32a0b594b1100
|
||||
inline static uint64_t rdmsr(uint32_t msr) {
|
||||
uint32_t low, high;
|
||||
|
||||
|
@ -204,9 +200,22 @@ static inline void write_cr3(uint32_t val) {
|
|||
asm volatile("mov %0, %%cr3" : : "r"(val));
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
/** @brief Flush a specific page entry in TLB
|
||||
* @param addr The (virtual) address of the page to flush
|
||||
*/
|
||||
=======
|
||||
static inline uint32_t read_cr4(void) {
|
||||
uint32_t val;
|
||||
asm volatile("mov %%cr4, %0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void write_cr4(uint32_t val) {
|
||||
asm volatile("mov %0, %%cr4" : : "r"(val));
|
||||
}
|
||||
|
||||
>>>>>>> a9ce93d119c2709a766c19b9cfa32a0b594b1100
|
||||
static inline void tlb_flush_one_page(uint32_t addr)
|
||||
{
|
||||
asm volatile("invlpg (%0)" : : "r"(addr) : "memory");
|
||||
|
@ -241,18 +250,18 @@ static inline uint32_t read_eflags(void)
|
|||
uint32_t read_eip(void);
|
||||
|
||||
/// A one-instruction-do-nothing
|
||||
#define NOP1 asm volatile ("nop")
|
||||
#define NOP1 asm volatile ("nop")
|
||||
/// Do nothing for 2 instructions
|
||||
#define NOP2 asm volatile ("nop;nop")
|
||||
#define NOP2 asm volatile ("nop;nop")
|
||||
/// Do nothing for 4 instructions
|
||||
#define NOP4 asm volatile ("nop;nop;nop;nop")
|
||||
#define NOP4 asm volatile ("nop;nop;nop;nop")
|
||||
/// Do nothing for 8 instructions
|
||||
#define NOP8 asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop")
|
||||
#define NOP8 asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop")
|
||||
#define HALT asm volatile ("hlt");
|
||||
|
||||
/** @brief Init several subsystems
|
||||
*
|
||||
* This function calls the initialization procedures for:
|
||||
* - SCC [if configured]
|
||||
* - GDT
|
||||
* - APIC
|
||||
* - PCI [if configured]
|
||||
|
@ -261,9 +270,6 @@ uint32_t read_eip(void);
|
|||
*/
|
||||
inline static int system_init(void)
|
||||
{
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
scc_init();
|
||||
#endif
|
||||
gdt_install();
|
||||
apic_init();
|
||||
#ifdef CONFIG_PCI
|
||||
|
|
|
@ -109,6 +109,22 @@ uint32_t apic_cpu_id(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t apic_version(void)
|
||||
{
|
||||
if (lapic)
|
||||
return lapic_read(APIC_VERSION) & 0xFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t apic_lvt_entries(void)
|
||||
{
|
||||
if (lapic)
|
||||
return (lapic_read(APIC_VERSION) >> 16) & 0xFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int has_apic(void)
|
||||
{
|
||||
return (lapic != 0);
|
||||
|
@ -238,6 +254,25 @@ int smp_init(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int lapic_reset(void)
|
||||
{
|
||||
uint32_t max_lvt = apic_lvt_entries();
|
||||
|
||||
lapic_write(APIC_SVR, 0x17F); // enable the apic and connect to the idt entry 127
|
||||
lapic_write(APIC_TPR, 0x00); // allow all interrupts
|
||||
lapic_write(APIC_LVT_T, 0x10000); // disable timer interrupt
|
||||
if (max_lvt >= 4)
|
||||
lapic_write(APIC_LVT_TSR, 0x10000); // disable thermal sensor interrupt
|
||||
if (max_lvt >= 5)
|
||||
lapic_write(APIC_LVT_PMC, 0x10000); // disable performance counter interrupt
|
||||
lapic_write(APIC_LINT0, 0x7C); // connect LINT0 to idt entry 124
|
||||
lapic_write(APIC_LINT1, 0x7D); // connect LINT1 to idt entry 125
|
||||
lapic_write(APIC_LVT_ER, 0x7E); // connect error to idt entry 126
|
||||
lapic_write(APIC_ID, 0x00); // reset boot processor id
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* detects the timer frequency of the APIC and restart
|
||||
* the APIC timer with the correct period
|
||||
|
@ -246,10 +281,13 @@ int apic_calibration(void)
|
|||
{
|
||||
uint8_t i;
|
||||
uint32_t flags;
|
||||
|
||||
#ifndef CONFIG_ROCKCREEK
|
||||
uint64_t ticks, old;
|
||||
uint32_t diff;
|
||||
#else
|
||||
uint64_t start, end, ticks;
|
||||
uint32_t diff;
|
||||
#endif
|
||||
|
||||
if (!has_apic())
|
||||
return -ENXIO;
|
||||
|
@ -257,29 +295,47 @@ int apic_calibration(void)
|
|||
lapic = map_region(0 /*lapic*/, lapic, 1, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
if (BUILTIN_EXPECT(!lapic, 0))
|
||||
return -ENXIO;
|
||||
kprintf("Mapped LAPIC at 0x%x\n", lapic);
|
||||
|
||||
if (ioapic) {
|
||||
size_t old = 0;
|
||||
|
||||
if (ioapic)
|
||||
ioapic = (ioapic_t*) map_region(0 /*(size_t)ioapic*/, (size_t) ioapic, 1, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
kprintf("Mapped IOAPIC at 0x%x\n", ioapic);
|
||||
|
||||
// map all processor entries
|
||||
for(i=0; i<MAX_CORES; i++) {
|
||||
if (apic_processors[i] && (old != (((size_t)apic_processors[i]) & 0xFFFFF000)))
|
||||
old = map_region(((size_t) apic_processors[i]) & 0xFFFFF000, ((size_t) apic_processors[i]) & 0xFFFFF000, 1, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_ROCKCREEK
|
||||
old = get_clock_tick();
|
||||
|
||||
/* wait for the next time slice */
|
||||
while((ticks = get_clock_tick()) - old == 0)
|
||||
;
|
||||
|
||||
HALT;
|
||||
|
||||
flags = irq_nested_disable();
|
||||
lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments
|
||||
lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it
|
||||
lapic_write(APIC_ICR, 0xFFFFFFFF);
|
||||
lapic_write(APIC_ICR, 0xFFFFFFFFUL);
|
||||
irq_nested_enable(flags);
|
||||
|
||||
/* wait 3 time slices to determine a ICR */
|
||||
while(get_clock_tick() - ticks < 3)
|
||||
;
|
||||
HALT;
|
||||
|
||||
diff = 0xFFFFFFFF - lapic_read(APIC_CCR);
|
||||
diff = 0xFFFFFFFFUL - lapic_read(APIC_CCR);
|
||||
diff = diff / 3;
|
||||
|
||||
flags = irq_nested_disable();
|
||||
lapic_reset();
|
||||
lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments
|
||||
lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it
|
||||
lapic_write(APIC_ICR, diff / 3);
|
||||
lapic_write(APIC_ICR, diff);
|
||||
irq_nested_enable(flags);
|
||||
|
||||
// Now, MetalSVM is able to use the APIC => Therefore, we disable the PIC
|
||||
outportb(0xA1, 0xFF);
|
||||
|
@ -290,39 +346,33 @@ int apic_calibration(void)
|
|||
* and possess no PIC timer. Therfore, we use the rdtsc to
|
||||
* to calibrate the APIC timer.
|
||||
*/
|
||||
uint64_t start, end, ticks;
|
||||
uint32_t diff;
|
||||
|
||||
if (!has_apic())
|
||||
return -ENXIO;
|
||||
|
||||
lapic = map_region(0 /*lapic*/, lapic, 1, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
if (BUILTIN_EXPECT(!lapic, 0))
|
||||
return -ENXIO;
|
||||
|
||||
if (ioapic)
|
||||
ioapic = (ioapic_t*) map_region(0 /*(size_t)ioapic*/, (size_t)ioapic, 1, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
flags = irq_nested_disable();
|
||||
|
||||
lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments
|
||||
lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it
|
||||
lapic_write(APIC_ICR, 0xFFFFFFFF);
|
||||
lapic_write(APIC_ICR, 0xFFFFFFFFUL);
|
||||
|
||||
/* wait 3 time slices to determine a ICR */
|
||||
rmb();
|
||||
start = rdtsc();
|
||||
do {
|
||||
flush_pipeline();
|
||||
rmb();
|
||||
end = rdtsc();
|
||||
ticks = end > start ? end - start : start - end;
|
||||
} while(ticks*TIMER_FREQ < 3*RC_REFCLOCKMHZ*1000000);
|
||||
} while(ticks*TIMER_FREQ < 3*RC_REFCLOCKMHZ*1000000UL);
|
||||
|
||||
diff = 0xFFFFFFFF - lapic_read(APIC_CCR);
|
||||
diff = 0xFFFFFFFFUL - lapic_read(APIC_CCR);
|
||||
diff = diff / 3;
|
||||
|
||||
lapic_reset();
|
||||
lapic_write(APIC_DCR, 0xB); // set it to 1 clock increments
|
||||
lapic_write(APIC_LVT_T, 0x2007B); // connects the timer to 123 and enables it
|
||||
lapic_write(APIC_ICR, diff / 3);
|
||||
lapic_write(APIC_ICR, diff);
|
||||
|
||||
irq_nested_enable(flags);
|
||||
#endif
|
||||
|
||||
kprintf("APIC calibration determines an ICR of 0x%x\n", diff / 3);
|
||||
kprintf("APIC calibration determines an ICR of 0x%x\n", diff);
|
||||
|
||||
flags = irq_nested_disable();
|
||||
#if MAX_CORES > 1
|
||||
|
@ -471,16 +521,20 @@ check_lapic:
|
|||
if (!lapic)
|
||||
goto out;
|
||||
|
||||
i = *((uint32_t*) (lapic+APIC_VERSION));
|
||||
kprintf("Found APIC at 0x%x\n", lapic);
|
||||
kprintf("Maximum LVT Entry: 0x%x\n", (i >> 16) & 0xFF);
|
||||
kprintf("APIC Version: 0x%x\n", i & 0xFF);
|
||||
kprintf("Maximum LVT Entry: 0x%x\n", apic_lvt_entries());
|
||||
kprintf("APIC Version: 0x%x\n", apic_version());
|
||||
|
||||
if (!((i & 0xFF) >> 4)) {
|
||||
if (!((apic_version() >> 4))) {
|
||||
kprintf("Currently, MetalSVM didn't supports extern APICs!\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (apic_lvt_entries() < 3) {
|
||||
kprintf("LVT is too small\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
|
@ -497,24 +551,28 @@ no_mp:
|
|||
goto check_lapic;
|
||||
}
|
||||
|
||||
static void apic_err_handler(struct state *s)
|
||||
{
|
||||
kprintf("Got APIC error 0x%x\n", lapic_read(APIC_ESR));
|
||||
}
|
||||
|
||||
int apic_init(void)
|
||||
{
|
||||
int ret;
|
||||
uint8_t i;
|
||||
|
||||
|
||||
ret = apic_probe();
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
lapic_write(APIC_TPR, 0x00); // allow all interrupts
|
||||
lapic_write(APIC_LVT_T, 0x10000); // disable timer interrupt
|
||||
lapic_write(APIC_LVT_PMC, 0x10000);// disable performance counter interrupt
|
||||
lapic_write(APIC_LINT0, 0x7C); // connect LINT0 to idt entry 124
|
||||
lapic_write(APIC_LINT1, 0x7D); // connect LINT1 to idt entry 125
|
||||
lapic_write(APIC_LVT_ER, 0x7E); // connect error to idt entry 126
|
||||
lapic_write(APIC_SVR, 0x17F); // enable the apic and connect to the idt entry 127
|
||||
// set APIC error handler
|
||||
irq_install_handler(126, apic_err_handler);
|
||||
|
||||
if (0) { //ioapic) {
|
||||
ret = lapic_reset();
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
if (ioapic) {
|
||||
// enable timer interrupt
|
||||
ioapic_inton(0, apic_processors[boot_processor]->id);
|
||||
// now lets turn everything else off
|
||||
|
|
|
@ -103,14 +103,7 @@ gdt_flush:
|
|||
flush2:
|
||||
ret
|
||||
|
||||
; Loads the IDT defined in '_idtp' into the processor.
|
||||
; This is declared in C as 'extern void idt_load();'
|
||||
global idt_load
|
||||
extern idtp
|
||||
idt_load:
|
||||
lidt [idtp]
|
||||
ret
|
||||
|
||||
; determines the current instruction pointer (after the jmp)
|
||||
global read_eip
|
||||
read_eip:
|
||||
pop eax ; Get the return address
|
||||
|
|
|
@ -69,6 +69,8 @@ int arch_fork(task_t* task)
|
|||
memcpy(kstacks[id], kstacks[curr_task->id], KERNEL_STACK_SIZE);
|
||||
task_state_segments[id].cr3 = (uint32_t) (virt_to_phys((size_t)task->pgd));
|
||||
task_state_segments[id].eflags = read_eflags();
|
||||
// the parent task will enable the IF flag
|
||||
task_state_segments[id].eflags |= (1 << 9);
|
||||
task_state_segments[id].esp0 = (uint32_t) kstacks[id] + KERNEL_STACK_SIZE - sizeof(size_t);
|
||||
|
||||
asm volatile("mov %%esp, %0" : "=r"(task_state_segments[id].esp));
|
||||
|
@ -76,18 +78,18 @@ int arch_fork(task_t* task)
|
|||
task_state_segments[id].esp += (uint32_t) kstacks[id];
|
||||
|
||||
asm volatile ("pusha");
|
||||
asm volatile ("pop %%eax" : "=a"(task_state_segments[id].edi));
|
||||
asm volatile ("pop %%eax" : "=a"(task_state_segments[id].esi));
|
||||
asm volatile ("pop %%eax" : "=a"(task_state_segments[id].ebp));
|
||||
asm volatile ("pop %0" : "=r"(task_state_segments[id].edi));
|
||||
asm volatile ("pop %0" : "=r"(task_state_segments[id].esi));
|
||||
asm volatile ("pop %0" : "=r"(task_state_segments[id].ebp));
|
||||
#ifdef WITH_FRAME_POINTER
|
||||
task_state_segments[id].ebp -= (uint32_t) kstacks[curr_task->id];
|
||||
task_state_segments[id].ebp += (uint32_t) kstacks[id];
|
||||
#endif
|
||||
asm volatile ("add $4, %%esp" ::: "%esp");
|
||||
asm volatile ("pop %%eax" : "=a"(task_state_segments[id].ebx));
|
||||
asm volatile ("pop %%eax" : "=a"(task_state_segments[id].edx));
|
||||
asm volatile ("pop %%eax" : "=a"(task_state_segments[id].ecx));
|
||||
asm volatile ("pop %%eax" : "=a"(task_state_segments[id].eax));
|
||||
asm volatile ("pop %0" : "=r"(task_state_segments[id].ebx));
|
||||
asm volatile ("pop %0" : "=r"(task_state_segments[id].edx));
|
||||
asm volatile ("pop %0" : "=r"(task_state_segments[id].ecx));
|
||||
asm volatile ("pop %0" : "=r"(task_state_segments[id].eax));
|
||||
|
||||
// This will be the entry point for the new task.
|
||||
task_state_segments[id].eip = read_eip();
|
||||
|
|
|
@ -72,14 +72,7 @@ typedef struct {
|
|||
* "Unhandled Interrupt" exception
|
||||
*/
|
||||
static idt_entry_t idt[256] = {[0 ... 255] = {0, 0, 0, 0, 0}};
|
||||
idt_ptr_t idtp;
|
||||
|
||||
/** @brief Loads the IDT
|
||||
*
|
||||
* The true definition lives in 'start.asm'
|
||||
*/
|
||||
extern void idt_load(void);
|
||||
|
||||
static idt_ptr_t idtp;
|
||||
/*
|
||||
* Use this function to set an entry in the IDT. Alot simpler
|
||||
* than twiddling with the GDT ;)
|
||||
|
@ -113,5 +106,5 @@ void idt_install(void)
|
|||
IDT_FLAG_PRESENT|IDT_FLAG_RING3|IDT_FLAG_32BIT|IDT_FLAG_TRAPGATE);
|
||||
|
||||
/* Points the processor's internal register to the new IDT */
|
||||
idt_load();
|
||||
asm volatile("lidt %0" : : "m" (idtp));
|
||||
}
|
||||
|
|
|
@ -23,16 +23,10 @@
|
|||
#include <metalsvm/processor.h>
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
#include <asm/RCCE_lib.h>
|
||||
#else
|
||||
/* disable optimization for the following functions */
|
||||
uint32_t detect_cpu_frequency(void) __attribute__((optimize(0)));
|
||||
#endif
|
||||
|
||||
static uint32_t cpu_freq = 0;
|
||||
|
||||
/* disable optimization for the following functions */
|
||||
void udelay(uint32_t usecs) __attribute__((optimize(0)));
|
||||
|
||||
uint32_t detect_cpu_frequency(void)
|
||||
{
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
@ -53,12 +47,14 @@ uint32_t detect_cpu_frequency(void)
|
|||
|
||||
/* wait for the next time slice */
|
||||
while((ticks = get_clock_tick()) - old == 0)
|
||||
;
|
||||
HALT;
|
||||
|
||||
rmb();
|
||||
start = rdtsc();
|
||||
/* wait a second to determine the frequency */
|
||||
while(get_clock_tick() - ticks < TIMER_FREQ)
|
||||
;
|
||||
HALT;
|
||||
rmb();
|
||||
end = rdtsc();
|
||||
|
||||
diff = end > start ? end - start : start - end;
|
||||
|
@ -82,6 +78,7 @@ void udelay(uint32_t usecs)
|
|||
uint64_t deadline = get_cpu_frequency() * usecs;
|
||||
|
||||
do {
|
||||
rmb();
|
||||
end = rdtsc();
|
||||
diff = end > start ? end - start : start - end;
|
||||
} while(diff < deadline);
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
#include <metalsvm/errno.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/multiboot.h>
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
#include <asm/RCCE_lib.h>
|
||||
#include <asm/SCC_API.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Virtual Memory Layout of the standard configuration
|
||||
|
@ -83,6 +87,12 @@ inline static size_t copy_page_table(task_t* task, uint32_t pgd_index, page_tabl
|
|||
|
||||
for(i=0; i<1024; i++) {
|
||||
if (pgt->entries[i] & 0xFFFFF000) {
|
||||
if (!(pgt->entries[i] & PG_USER)) {
|
||||
// Kernel page => copy only page entries
|
||||
new_pgt->entries[i] = pgt->entries[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
phyaddr = get_page();
|
||||
if (!phyaddr)
|
||||
continue;
|
||||
|
@ -136,9 +146,10 @@ int create_pgd(task_t* task, int copy)
|
|||
|
||||
spinlock_lock(&kslock);
|
||||
|
||||
for(i=0; i<KERNEL_SPACE/(1024*PAGE_SIZE); i++) {
|
||||
for(i=0; i<1024; i++) {
|
||||
pgd->entries[i] = boot_pgd.entries[i];
|
||||
if (pgd->entries[i])
|
||||
// only kernel entries will be copied
|
||||
if (pgd->entries[i] && !(pgd->entries[i] & PG_USER))
|
||||
pgt->entries[i] = pgt_container->entries[i];
|
||||
}
|
||||
|
||||
|
@ -161,6 +172,8 @@ int create_pgd(task_t* task, int copy)
|
|||
for (i=KERNEL_SPACE/(1024*PAGE_SIZE); i<1024; i++) {
|
||||
if (!(curr_task->pgd->entries[i]))
|
||||
continue;
|
||||
if (!(curr_task->pgd->entries[i] & PG_USER))
|
||||
continue;
|
||||
|
||||
phyaddr = copy_page_table(task, i, (page_table_t*) ((KERNEL_SPACE - 1024*PAGE_SIZE + i*PAGE_SIZE) & 0xFFFFF000), &counter);
|
||||
if (phyaddr) {
|
||||
|
@ -190,8 +203,8 @@ int drop_pgd(void)
|
|||
|
||||
spinlock_lock(&task->pgd_lock);
|
||||
|
||||
for(i=KERNEL_SPACE/(1024*PAGE_SIZE); i<1024; i++) {
|
||||
if (pgd->entries[i] & 0xFFFFF000) {
|
||||
for(i=0; i<1024; i++) {
|
||||
if (pgd->entries[i] & PG_USER) {
|
||||
put_page(pgd->entries[i] & 0xFFFFF000);
|
||||
pgd->entries[i] = 0;
|
||||
}
|
||||
|
@ -324,7 +337,7 @@ size_t map_region(size_t viraddr, size_t phyaddr, uint32_t npages, uint32_t flag
|
|||
index = (viraddr >> 12) & 0x3FF;
|
||||
if (BUILTIN_EXPECT(pgt->entries[index], 0)) {
|
||||
spinlock_unlock(pgd_lock);
|
||||
kprintf("0x%x is already maped\n");
|
||||
kprintf("0x%x is already maped\n", viraddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -335,6 +348,10 @@ size_t map_region(size_t viraddr, size_t phyaddr, uint32_t npages, uint32_t flag
|
|||
|
||||
if (flags & MAP_NO_CACHE)
|
||||
pgt->entries[index] |= PG_PCD;
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
if (flags & MAP_MPE)
|
||||
pgt->entries[index] |= PG_MPE;
|
||||
#endif
|
||||
|
||||
if (flags & MAP_USER_SPACE)
|
||||
atomic_int32_inc(&task->user_usage);
|
||||
|
@ -638,8 +655,9 @@ int arch_paging_init(void)
|
|||
* of course, mb_info has to map into the kernel space
|
||||
*/
|
||||
if (mb_info)
|
||||
map_region((size_t) mb_info, (size_t) mb_info, 1, MAP_KERNEL_SPACE);
|
||||
map_region((size_t) mb_info & 0xFFFFF000, (size_t) mb_info & 0xFFFFF000, 1, MAP_KERNEL_SPACE);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Map reserved memory regions into the kernel space
|
||||
*/
|
||||
|
@ -657,6 +675,7 @@ int arch_paging_init(void)
|
|||
mmap++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Modules like the init ram disk are already loaded.
|
||||
|
@ -675,6 +694,25 @@ int arch_paging_init(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
// map SCC's bootinfo
|
||||
map_region(SCC_BOOTINFO, SCC_BOOTINFO, 1, MAP_KERNEL_SPACE);
|
||||
|
||||
// map the initial ramdisk
|
||||
npages = bootinfo->size / PAGE_SIZE;
|
||||
if (bootinfo->size % PAGE_SIZE)
|
||||
npages++;
|
||||
map_region(bootinfo->addr, bootinfo->addr, npages, MAP_KERNEL_SPACE);
|
||||
|
||||
// map SCC's configuration registers
|
||||
viraddr = map_region(CRB_X0_Y0, CRB_X0_Y0, (CRB_OWN-CRB_X0_Y0+16*1024*1024)/PAGE_SIZE, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||
kprintf("Map configuration registers at 0x%x\n", viraddr);
|
||||
|
||||
// map SCC's message passing buffers
|
||||
viraddr = map_region(MPB_X0_Y0, MPB_X0_Y0, (MPB_OWN-MPB_X0_Y0+16*1024*1024)/PAGE_SIZE, MAP_KERNEL_SPACE|MAP_MPE);
|
||||
kprintf("Map message passing buffers at 0x%x\n", viraddr);
|
||||
#endif
|
||||
|
||||
/* enable paging */
|
||||
write_cr3((uint32_t) &boot_pgd);
|
||||
i = read_cr0();
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
// GLOBAL VARIABLES USED BY THE LIBRARY
|
||||
//......................................................................................
|
||||
int RCCE_NP; // number of participating cores
|
||||
int RC_REFCLOCKMHZ=533; // baseline CPU frequency (MHz)
|
||||
int RC_REFCLOCKMHZ; // baseline CPU frequency (MHz)
|
||||
int RC_MY_COREID; // physical ID of calling core
|
||||
int RC_COREID[RCCE_MAXNP]; // array of physical core IDs for all participating
|
||||
// cores, sorted by rank
|
||||
|
@ -232,7 +232,7 @@ int RCCE_init(
|
|||
unsigned int RCCE_SHM_BUFFER_offset ,result, rd_slot_nbr, wr_slot_nbr;
|
||||
#endif
|
||||
void *nothing = NULL;
|
||||
|
||||
|
||||
#ifdef SCC
|
||||
// Copperridge specific initialization...
|
||||
InitAPI(0); //fflush(0)
|
||||
|
|
|
@ -10,12 +10,7 @@
|
|||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of MetalSVM.
|
||||
*/
|
||||
* WITHOUT WARRANTIES OR COND */
|
||||
|
||||
#include <metalsvm/stdio.h>
|
||||
#include <metalsvm/errno.h>
|
||||
|
@ -27,22 +22,20 @@
|
|||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
||||
#define CCR_INTR_ACTIVE 0x02
|
||||
bootinfo_t* bootinfo = (bootinfo_t*) SCC_BOOTINFO;
|
||||
|
||||
//scc_info_t scc_info;
|
||||
static char* rcce_argv[] = {"MetalSVM", "1", "533", "0"};
|
||||
static int rcce_argc = 4;
|
||||
/* PSE bit for Pentium+ equals MPE (message buffer enable) flag in RCK! So, use it to create _PAGE_MPB symbol... */
|
||||
#define _CR4_MPE 0x00000800
|
||||
|
||||
/*
|
||||
* This is a modified MPB program, which is part of the RCCE distribution (src/mpb.c).
|
||||
* This is the modified MPB program, which is part of the RCCE distribution (src/mpb.c).
|
||||
*
|
||||
* This function clears the local MPB and resets the test&set register.
|
||||
*/
|
||||
static int scc_reset(void)
|
||||
static int scc_clear(void)
|
||||
{
|
||||
int tmp, x, y, z, offset;
|
||||
|
||||
// Initialize API
|
||||
InitAPI(0);
|
||||
|
||||
|
||||
// Find out who I am...
|
||||
tmp=ReadConfigReg(CRB_OWN+MYTILEID);
|
||||
x=(tmp>>3) & 0x0f; // bits 06:03
|
||||
|
@ -69,74 +62,33 @@ static int scc_reset(void)
|
|||
|
||||
int scc_init(void)
|
||||
{
|
||||
// uint32_t x, y, z;
|
||||
// uint32_t tmp;
|
||||
int num_ranks;
|
||||
int my_rank;
|
||||
|
||||
return 0;
|
||||
int i, my_rank;
|
||||
|
||||
kprintf("Initialize Rock Creek!\n");
|
||||
if (RCCE_init(&rcce_argc, &rcce_argv) != RCCE_SUCCESS)
|
||||
kprintf("address of the initrd: 0x%x\n", bootinfo->addr);
|
||||
kprintf("size of the initrd: %d\n", bootinfo->size);
|
||||
kprintf("rcce argc = %d\n", bootinfo->argc);
|
||||
for(i=0; i<bootinfo->argc; i++)
|
||||
kprintf("rcce argv[%d] = %s\n", i, bootinfo->argv[i]);
|
||||
|
||||
if (RCCE_init(&bootinfo->argc, &bootinfo->argv) != RCCE_SUCCESS)
|
||||
return -ENODEV;
|
||||
|
||||
my_rank = RCCE_ue();
|
||||
num_ranks = RCCE_num_ues();
|
||||
kprintf("Got rank %d of %d ranks\n", my_rank, num_ranks);
|
||||
|
||||
/* Enable Messagepassing in CR4 */
|
||||
uint32_t cr4 = read_cr4();
|
||||
cr4 = cr4 | _CR4_MPE;
|
||||
write_cr4(cr4);
|
||||
|
||||
i = ReadConfigReg(CRB_OWN+GLCFG0);
|
||||
kprintf("glcfg0 0x%x\n", i);
|
||||
|
||||
/* synchronize before starting MetalSVM: */
|
||||
RCCE_barrier(&RCCE_COMM_WORLD);
|
||||
|
||||
/*tmp = *((uint32_t*) (CRB_OWN+MYTILEID));
|
||||
x=(tmp>>3) & 0x0f; // bits 06:03
|
||||
y=(tmp>>7) & 0x0f; // bits 10:07
|
||||
z=(tmp ) & 0x07; // bits 02:00
|
||||
scc_info.pid = PID(x, y, z);
|
||||
kprintf("SCC Processor Id: %u (%u,%u,%u)\n", scc_info.pid, x, y, z);
|
||||
*/
|
||||
/* default values for 16 GB system */
|
||||
/*scc_info.private_mem[0].low = 0x00;
|
||||
scc_info.private_mem[0].high = 0x13FFFFFF;
|
||||
scc_info.private_mem[1].low = 0xFF000000;
|
||||
scc_info.private_mem[1].high = 0xFFFFFFFF;
|
||||
*/
|
||||
// tmp = *((uint32_t*) (CRB_OWN+GCBCFG));
|
||||
// tmp = (tmp & 0x3FFFFFF) >> 7;
|
||||
//kprintf("Own GCBCFG is 0x%x\n", tmp);
|
||||
/* if (tmp == 0x70E1) {
|
||||
scc_info.tile_frequency = 800;
|
||||
scc_info.router_frequency = 1600;
|
||||
} else {
|
||||
scc_info.tile_frequency = 533;
|
||||
scc_info.router_frequency = 800;
|
||||
}
|
||||
*/
|
||||
|
||||
/* kprintf("The default tile frequency is %u MHz\nThe default router frequency is %u MHz\n",
|
||||
scc_info.tile_frequency, scc_info.router_frequency);
|
||||
|
||||
if (z == 0)
|
||||
tmp = *((uint32_t*) (CRB_OWN+GLCFG0));
|
||||
else if (z == 1)
|
||||
tmp = *((uint32_t*) (CRB_OWN+GLCFG1));
|
||||
else
|
||||
tmp = 0;
|
||||
*/
|
||||
/* set INTR to enable maskable interrupts */
|
||||
/* tmp = tmp | CCR_INTR_ACTIVE;
|
||||
if (z == 0)
|
||||
*((uint32_t*) (CRB_OWN+GLCFG0)) = tmp;
|
||||
else if (z == 1)
|
||||
*((uint32_t*) (CRB_OWN+GLCFG1)) = tmp;
|
||||
*/
|
||||
/* reload core configuration */
|
||||
/* tmp = 0;
|
||||
if (z == 0)
|
||||
tmp = *((uint32_t*) (CRB_OWN+GLCFG0));
|
||||
else if (z == 1)
|
||||
tmp = *((uint32_t*) (CRB_OWN+GLCFG1));
|
||||
kprintf("Core Configuration %u: 0x%x\n", z, tmp);
|
||||
*/
|
||||
//RCCE_barrier(&RCCE_COMM_WORLD);
|
||||
|
||||
kputs("Now, the SCC is initialized!\n");
|
||||
|
||||
|
|
10
fs/initrd.c
10
fs/initrd.c
|
@ -23,6 +23,7 @@
|
|||
#include <metalsvm/fs.h>
|
||||
#include <metalsvm/errno.h>
|
||||
#include <asm/multiboot.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
static vfs_node_t initrd_root;
|
||||
|
||||
|
@ -213,8 +214,10 @@ int initrd_init(void)
|
|||
{
|
||||
dir_block_t* dir_block;
|
||||
vfs_node_t* tmp;
|
||||
#ifdef CONFIG_MULTIBOOT
|
||||
#if defined(CONFIG_ROCKCREEK) || defined(CONFIG_MULTIBOOT)
|
||||
uint32_t i, j, k, l;
|
||||
#endif
|
||||
#ifdef CONFIG_MULTIBOOT
|
||||
uint32_t mods_count = 0;
|
||||
multiboot_module_t* mmodule = NULL;
|
||||
|
||||
|
@ -256,6 +259,10 @@ int initrd_init(void)
|
|||
#ifdef CONFIG_MULTIBOOT
|
||||
for(i=0; i<mods_count; i++) {
|
||||
initrd_header_t* header = (initrd_header_t*) mmodule[i].mod_start;
|
||||
#elif defined(CONFIG_ROCKCREEK)
|
||||
for(i=0; i<1; i++) {
|
||||
initrd_header_t* header = (initrd_header_t*) bootinfo->addr;
|
||||
#endif
|
||||
initrd_file_desc_t* file_desc;
|
||||
vfs_node_t* new_node;
|
||||
|
||||
|
@ -328,6 +335,7 @@ int initrd_init(void)
|
|||
next_file:
|
||||
file_desc++;
|
||||
}
|
||||
#if defined(CONFIG_ROCKCREEK) || defined(CONFIG_MULTIBOOT)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ extern "C" {
|
|||
#define PRIVATE_MEM1_END 0x13FFFFFF
|
||||
#define PRIVATE_MEM2_START 0xFF000000
|
||||
#define PRIVATE_MEM2_END 0xFFFFFFFF
|
||||
#define SCC_BOOTINFO 0x80000
|
||||
|
||||
#define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b))
|
||||
//#define BUILTIN_EXPECT(exp, b) (exp)
|
||||
|
|
|
@ -45,7 +45,9 @@ extern "C" {
|
|||
#define MAP_HEAP (1 << 5)
|
||||
#define MAP_CODE (1 << 6)
|
||||
#define MAP_READONLY (1 << 7)
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
#define MAP_MPE (1 << 8)
|
||||
#endif
|
||||
void NORETURN abort(void);
|
||||
|
||||
/** @brief Kernel's memory allocator function.
|
||||
|
@ -83,6 +85,7 @@ void kfree(void*, size_t);
|
|||
* @return Long value of the parsed numerical string
|
||||
*/
|
||||
long strtol(const char* str, char** endptr, int base);
|
||||
unsigned long strtoul(const char* nptr, char** endptr, int base);
|
||||
|
||||
/** @brief ASCII to integer
|
||||
*
|
||||
|
|
|
@ -89,6 +89,9 @@ int main(void)
|
|||
#endif
|
||||
multitasking_init();
|
||||
mmu_init();
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
scc_init();
|
||||
#endif
|
||||
initrd_init();
|
||||
|
||||
irq_enable();
|
||||
|
@ -111,7 +114,7 @@ int main(void)
|
|||
reschedule();
|
||||
|
||||
while(1) {
|
||||
NOP8;
|
||||
HALT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -126,7 +126,7 @@ static void NORETURN do_exit(int arg) {
|
|||
|
||||
kputs("Kernel panic: scheduler found no valid task\n");
|
||||
while(1) {
|
||||
NOP8;
|
||||
HALT;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
C_source := string.c stdio.c printf.c sprintf.c ucmpdi2.c lshrdi3.c qdivrem.c udivdi3.c divdi3.c moddi3.c umoddi3.c strtol.c
|
||||
C_source := string.c stdio.c printf.c sprintf.c ucmpdi2.c lshrdi3.c qdivrem.c udivdi3.c divdi3.c moddi3.c umoddi3.c strtol.c strtoul.c
|
||||
MODULE := libkern
|
||||
|
||||
include $(TOPDIR)/Makefile.inc
|
||||
|
|
112
libkern/strtoul.c
Normal file
112
libkern/strtoul.c
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Chris Torek.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* From: @(#)strtoul.c 8.1 (Berkeley) 6/4/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* The code has been taken from FreeBSD (sys/libkern/strtoul.c) and is therefore
|
||||
* BSD-licensed. Unnecessary functions have been removed and all typedefs required
|
||||
* have been added.
|
||||
*/
|
||||
|
||||
/* MetalSVM prelude */
|
||||
#include <metalsvm/stddef.h>
|
||||
#include <metalsvm/ctype.h>
|
||||
#include <asm/limits.h>
|
||||
|
||||
/*
|
||||
* Convert a string to an unsigned long integer.
|
||||
*
|
||||
* Ignores `locale' stuff. Assumes that the upper and lower case
|
||||
* alphabets and digits are each contiguous.
|
||||
*/
|
||||
unsigned long
|
||||
strtoul(nptr, endptr, base)
|
||||
const char *nptr;
|
||||
char **endptr;
|
||||
int base;
|
||||
{
|
||||
const char *s = nptr;
|
||||
unsigned long acc;
|
||||
unsigned char c;
|
||||
unsigned long cutoff;
|
||||
int neg = 0, any, cutlim;
|
||||
|
||||
/*
|
||||
* See strtol for comments as to the logic used.
|
||||
*/
|
||||
do {
|
||||
c = *s++;
|
||||
} while (isspace(c));
|
||||
if (c == '-') {
|
||||
neg = 1;
|
||||
c = *s++;
|
||||
} else if (c == '+')
|
||||
c = *s++;
|
||||
if ((base == 0 || base == 16) &&
|
||||
c == '0' && (*s == 'x' || *s == 'X')) {
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
|
||||
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
|
||||
for (acc = 0, any = 0;; c = *s++) {
|
||||
if (!isascii(c))
|
||||
break;
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
else if (isalpha(c))
|
||||
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
||||
else
|
||||
break;
|
||||
if (c >= base)
|
||||
break;
|
||||
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
|
||||
any = -1;
|
||||
else {
|
||||
any = 1;
|
||||
acc *= base;
|
||||
acc += c;
|
||||
}
|
||||
}
|
||||
if (any < 0) {
|
||||
acc = ULONG_MAX;
|
||||
} else if (neg)
|
||||
acc = -acc;
|
||||
if (endptr != 0)
|
||||
*((const char **)endptr) = any ? s - 1 : nptr;
|
||||
return (acc);
|
||||
}
|
||||
|
24
mm/memory.c
24
mm/memory.c
|
@ -126,6 +126,13 @@ int mmu_init(void)
|
|||
if (mb_info && (mb_info->flags & MULTIBOOT_INFO_MODS)) {
|
||||
multiboot_module_t* mmodule = (multiboot_module_t*) mb_info->mods_addr;
|
||||
|
||||
/*
|
||||
* Mark the mb_info as used.
|
||||
*/
|
||||
page_set_mark((size_t)mb_info / PAGE_SIZE);
|
||||
atomic_int32_inc(&total_allocated_pages);
|
||||
atomic_int32_dec(&total_available_pages);
|
||||
|
||||
for(i=0; i<mb_info->mods_count; i++, mmodule++) {
|
||||
for(addr=mmodule->mod_start; addr<mmodule->mod_end; addr+=PAGE_SIZE) {
|
||||
page_set_mark(addr / PAGE_SIZE);
|
||||
|
@ -150,6 +157,23 @@ int mmu_init(void)
|
|||
atomic_int32_inc(&total_pages);
|
||||
atomic_int32_inc(&total_available_pages);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark the bootinfo as used.
|
||||
*/
|
||||
page_set_mark((size_t)bootinfo / PAGE_SIZE);
|
||||
atomic_int32_inc(&total_allocated_pages);
|
||||
atomic_int32_dec(&total_available_pages);
|
||||
|
||||
/*
|
||||
* The init ram disk are already loaded.
|
||||
* Therefore, we set these pages as used.
|
||||
*/
|
||||
for(addr=bootinfo->addr; addr < bootinfo->addr+bootinfo->size; addr+=PAGE_SIZE) {
|
||||
page_set_mark(addr / PAGE_SIZE);
|
||||
atomic_int32_inc(&total_allocated_pages);
|
||||
atomic_int32_dec(&total_available_pages);
|
||||
}
|
||||
#else
|
||||
#error Currently, MetalSVM supports only the Multiboot specification or the RockCreek processor!
|
||||
#endif
|
||||
|
|
|
@ -34,7 +34,7 @@ int main(int argc, char** argv)
|
|||
|
||||
printf("Create child process...\n");
|
||||
|
||||
pid = fork();
|
||||
pid = 42; //fork();
|
||||
if (pid == 0) { // child
|
||||
char* newargs[] = {"/bin/hello", "one", "two", "three", NULL};
|
||||
char* newenv[] = {"USER=root", "PATH=/bin:/sbin:/usr/bin", "PWD=/", "TEMP=/tmp", NULL};
|
||||
|
|
|
@ -17,7 +17,7 @@ default: all
|
|||
|
||||
all: make_initrd initrd.img
|
||||
|
||||
initrd.img: $(EXECFILES)
|
||||
initrd.img: $(EXECFILES) make_initrd
|
||||
./make_initrd /bin $(foreach FILE, $(EXECFILES), $(FILE) $(shell basename $(FILE)))
|
||||
|
||||
make_initrd: make_initrd.o
|
||||
|
@ -35,7 +35,13 @@ scc_setup.bin: scc_setup.asm
|
|||
reset_vector.bin: reset_vector.o
|
||||
ld --oformat binary -Ttext 0 -melf_i386 -o $@ $<
|
||||
|
||||
SCC: scc_setup.bin reset_vector.bin
|
||||
scc_bootinfo.asm: bootinfo.sh
|
||||
./bootinfo.sh 0x00400000 initrd.img 1 533 0 > scc_bootinfo.asm
|
||||
|
||||
scc_bootinfo.bin: scc_bootinfo.asm
|
||||
$(NASM) $(NASMFLAGS) -o $@ $<
|
||||
|
||||
SCC: scc_bootinfo.bin scc_setup.bin reset_vector.bin initrd.img
|
||||
cp ../metalsvm.elf .
|
||||
$(CROSS_OBJCOPY) -j .mboot -j .text -j .data -j .rodata -j .bss -O binary metalsvm.elf metalsvm.bin
|
||||
chmod a-x *.bin
|
||||
|
@ -44,7 +50,7 @@ SCC: scc_setup.bin reset_vector.bin
|
|||
sccMerge -noimage -m 8 -n 12 -force ./metalsvm.mt
|
||||
|
||||
clean:
|
||||
$(RM) -rf *.o *~ make_initrd *.bin *.obj *.hex *.elf obj
|
||||
$(RM) -rf *.o *~ make_initrd initrd.img *.bin *.obj *.hex *.elf obj
|
||||
|
||||
depend:
|
||||
$(CC) -MM $(CFLAGS) *.c > Makefile.dep
|
||||
|
|
39
tools/bootinfo.sh
Executable file
39
tools/bootinfo.sh
Executable file
|
@ -0,0 +1,39 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
IMAGESIZE=$(stat -c%s "$2")
|
||||
NCORES=$3
|
||||
ORG=0x80000
|
||||
echo "[BITS 16]"
|
||||
echo "SECTION .data"
|
||||
echo "ORG $ORG"
|
||||
echo "addr DD $1 ; start addresss of the initrd"
|
||||
echo "size DD $IMAGESIZE ; size of the initrd"
|
||||
|
||||
shift
|
||||
shift
|
||||
shift
|
||||
ARGC=`expr $# + 2`
|
||||
|
||||
echo "argc DD $ARGC"
|
||||
echo "argv DD Largv"
|
||||
echo "Largv EQU \$"
|
||||
echo -n " DD name, ncores"
|
||||
for i in $*
|
||||
do
|
||||
echo -n ", L$i"
|
||||
done
|
||||
echo ""
|
||||
|
||||
echo "name EQU \$"
|
||||
echo " DB \"MetalSVM\", 0"
|
||||
echo "ncores EQU \$"
|
||||
echo " DB \"$NCORES\", 0"
|
||||
|
||||
for i in $*
|
||||
do
|
||||
echo "L$i EQU \$"
|
||||
echo " DB \"$i\", 0"
|
||||
done
|
||||
|
||||
echo "gap:"
|
||||
echo "TIMES 4096-(\$-\$\$) DB 0"
|
|
@ -1,3 +1,4 @@
|
|||
0x00080000 scc_bootinfo.bin
|
||||
0x00090200 scc_setup.bin
|
||||
0x00100000 metalsvm.bin
|
||||
0x00400000 initrd.img
|
||||
|
|
|
@ -28,53 +28,11 @@ _start:
|
|||
|
||||
msg db "?ello from MetalSVM bootloader!!",0
|
||||
|
||||
enable_A20:
|
||||
call a20wait
|
||||
mov al,0xAD
|
||||
out 0x64,al
|
||||
|
||||
call a20wait
|
||||
mov al,0xD0
|
||||
out 0x64,al
|
||||
|
||||
call a20wait2
|
||||
in al,0x60
|
||||
push eax
|
||||
|
||||
call a20wait
|
||||
mov al,0xD1
|
||||
out 0x64,al
|
||||
|
||||
call a20wait
|
||||
pop eax
|
||||
or al,2
|
||||
out 0x60,al
|
||||
|
||||
call a20wait
|
||||
mov al,0xAE
|
||||
out 0x64,al
|
||||
|
||||
call a20wait
|
||||
ret
|
||||
|
||||
a20wait:
|
||||
in al,0x64
|
||||
test al,2
|
||||
jnz a20wait
|
||||
ret
|
||||
|
||||
a20wait2:
|
||||
in al,0x64
|
||||
test al,1
|
||||
jz a20wait2
|
||||
ret
|
||||
|
||||
_realstart:
|
||||
; IRQs are already disabled by reset_vector
|
||||
; cli
|
||||
|
||||
lgdt [gdtr]
|
||||
; call enable_A20
|
||||
|
||||
; switch to protected mode by setting PE bit
|
||||
mov eax, cr0
|
||||
|
|
Loading…
Add table
Reference in a new issue