Merge branch 'master' of git.lfbs.rwth-aachen.de:metalsvm into rcce
This commit is contained in:
commit
ba1388c13d
10 changed files with 104 additions and 67 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -5,3 +5,6 @@
|
|||
*.sym
|
||||
*.pcap
|
||||
*.img
|
||||
*.log
|
||||
*.a
|
||||
*.DS_Store
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -114,7 +114,7 @@ int main(void)
|
|||
reschedule();
|
||||
|
||||
while(1) {
|
||||
NOP8;
|
||||
HALT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -104,7 +104,7 @@ static void NORETURN do_exit(int arg) {
|
|||
|
||||
kputs("Kernel panic: scheduler found no valid task\n");
|
||||
while(1) {
|
||||
NOP8;
|
||||
HALT;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue