Merge branch 'master' of git.lfbs.rwth-aachen.de:metalsvm into rcce

This commit is contained in:
Stefan Lankes 2011-04-08 07:26:55 -07:00
commit ba1388c13d
10 changed files with 104 additions and 67 deletions

3
.gitignore vendored
View file

@ -5,3 +5,6 @@
*.sym
*.pcap
*.img
*.log
*.a
*.DS_Store

View file

@ -33,6 +33,7 @@ extern "C" {
#define APIC_TPR 0x0080 // Task Priority Regster
#define APIC_EOI 0x00B0 // EOI Register
#define APIC_SVR 0x00F0 // Spurious Interrupt Vector Register
#define APIC_ESR 0x0280 // Error Status Regsiter
#define APIC_ICR1 0x0300 // Interrupt Command Register [0-31]
#define APIC_ICR2 0x0310 // Interrupt Command Register [32-63]
#define APIC_LVT_T 0x0320 // LVT Timer Register

View file

@ -31,7 +31,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;
}
inline static void irq_enable(void) {
@ -39,7 +41,8 @@ inline static void irq_enable(void) {
}
inline static void irq_nested_enable(uint32_t flags) {
asm volatile("pushl %0; popf" : : "r"(flags) : "memory");
if (flags)
irq_enable();
}
#ifdef __cplusplus

View file

@ -71,14 +71,6 @@ 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));
}
inline static void flush_pipeline(void) {
uint32_t low = 0;
uint32_t high = 0;
uint32_t code = 0;
asm volatile ("cpuid" : "=a"(low), "=d"(high) : "0"(code) : "%ebx", "%ecx");
}
inline static uint64_t rdmsr(uint32_t msr) {
uint32_t low, high;

View file

@ -76,8 +76,7 @@ static inline void lapic_write(uint32_t addr, uint32_t value)
* to avoid a pentium bug, we have to read a apic register
* before we write a value to this register
*/
asm volatile ("cmpl (%0), %%eax; movl %1, (%0)" :: "r"(lapic+addr), "r"(value));
//asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(lapic+addr), "b"(value) : "%edx");
asm volatile ("movl (%%eax), %%edx; movl %%ebx, (%%eax)" :: "a"(lapic+addr), "b"(value) : "%edx");
//*((volatile uint32_t*) (lapic+addr)) = value;
}
@ -255,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
@ -263,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;
@ -274,30 +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, 0xFFFFFFFFUL);
irq_nested_enable(flags);
/* wait 3 time slices to determine a ICR */
while(get_clock_tick() - ticks < 3)
;
HALT;
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);
irq_nested_enable(flags);
// Now, MetalSVM is able to use the APIC => Therefore, we disable the PIC
outportb(0xA1, 0xFF);
@ -308,27 +346,17 @@ 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, 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*1000000UL);
@ -336,9 +364,12 @@ int apic_calibration(void)
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);
irq_nested_enable(flags);
#endif
kprintf("APIC calibration determines an ICR of 0x%x\n", diff);
@ -520,31 +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;
uint32_t v;
uint32_t max_lvt;
ret = apic_probe();
if (!ret)
return ret;
max_lvt = apic_lvt_entries();
// set APIC error handler
irq_install_handler(126, apic_err_handler);
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
ret = lapic_reset();
if (!ret)
return ret;
if (0) { //ioapic) {
if (ioapic) {
// enable timer interrupt
ioapic_inton(0, apic_processors[boot_processor]->id);
// now lets turn everything else off

View file

@ -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();

View file

@ -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);

View file

@ -87,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;
@ -140,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];
}
@ -165,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) {
@ -194,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;
}
@ -328,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;
}
@ -646,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
*/
@ -665,6 +675,7 @@ int arch_paging_init(void)
mmap++;
}
}
#endif
/*
* Modules like the init ram disk are already loaded.

View file

@ -114,7 +114,7 @@ int main(void)
reschedule();
while(1) {
NOP8;
HALT;
}
return 0;

View file

@ -104,7 +104,7 @@ static void NORETURN do_exit(int arg) {
kputs("Kernel panic: scheduler found no valid task\n");
while(1) {
NOP8;
HALT;
}
}