Merge branch 'master' into readwrite
Conflicts: .gitignore arch/x86/include/asm/apic.h arch/x86/include/asm/processor.h
This commit is contained in:
commit
b6079272c1
15 changed files with 313 additions and 251 deletions
|
@ -28,43 +28,28 @@ extern "C" {
|
|||
|
||||
#define MP_FLT_SIGNATURE 0x5f504d5f
|
||||
|
||||
/// Local APIC ID Register
|
||||
#define APIC_ID 0x0020
|
||||
/// Local APIC Version Register
|
||||
#define APIC_VERSION 0x0030
|
||||
/// Task Priority Regster
|
||||
#define APIC_TPR 0x0080
|
||||
/// EOI Register
|
||||
#define APIC_EOI 0x00B0
|
||||
/// Spurious Interrupt Vector Register
|
||||
#define APIC_SVR 0x00F0
|
||||
/// Interrupt Command Register [bits 0-31]
|
||||
#define APIC_ICR1 0x0300
|
||||
/// Interrupt Command Register [bits 32-63]
|
||||
#define APIC_ICR2 0x0310
|
||||
/// LVT Timer Register
|
||||
#define APIC_LVT_T 0x0320
|
||||
/// LVT Performance Monitoring Counters Register
|
||||
#define APIC_LVT_PMC 0x0340
|
||||
/// LVT LINT0 Register
|
||||
#define APIC_LINT0 0x0350
|
||||
/// LVT LINT1 Register
|
||||
#define APIC_LINT1 0x0360
|
||||
/// LVT Error Register
|
||||
#define APIC_LVT_ER 0x0370
|
||||
/// Initial Count Register
|
||||
#define APIC_ICR 0x0380
|
||||
/// Current Count Register
|
||||
#define APIC_CCR 0x0390
|
||||
/// Divide Configuration Register
|
||||
#define APIC_DCR 0x03E0
|
||||
|
||||
/// Register index: ID
|
||||
#define IOAPIC_REG_ID 0x0000
|
||||
/// Register index: version
|
||||
#define IOAPIC_REG_VER 0x0001
|
||||
/// Redirection table base
|
||||
#define IOAPIC_REG_TABLE 0x0010
|
||||
#define APIC_ID 0x0020 // Local APIC ID Register
|
||||
#define APIC_VERSION 0x0030 // Local APIC Version Register
|
||||
#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
|
||||
#define APIC_LVT_TSR 0x0330 // LVT Thermal Sensor Register
|
||||
#define APIC_LVT_PMC 0x0340 // LVT Performance Monitoring Counters Register
|
||||
#define APIC_LINT0 0x0350 // LVT LINT0 Register
|
||||
#define APIC_LINT1 0x0360 // LVT LINT1 Register
|
||||
#define APIC_LVT_ER 0x0370 // LVT Error Register
|
||||
#define APIC_ICR 0x0380 // Initial Count Register
|
||||
#define APIC_CCR 0x0390 // Current Count Register
|
||||
#define APIC_DCR 0x03E0 // Divide Configuration Register
|
||||
|
||||
#define IOAPIC_REG_ID 0x0000 // Register index: ID
|
||||
#define IOAPIC_REG_VER 0x0001 // Register index: version
|
||||
#define IOAPIC_REG_TABLE 0x0010 // Redirection table base
|
||||
|
||||
#define APIC_DEST_SELF 0x40000
|
||||
#define APIC_DEST_ALLINC 0x80000
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -40,22 +40,6 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
/*#define SCC_PMEM_REGIONS 2
|
||||
|
||||
typedef struct {
|
||||
uint32_t low;
|
||||
uint32_t high;
|
||||
} mem_region_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;*/
|
||||
|
||||
int scc_init(void);
|
||||
#endif
|
||||
|
||||
|
@ -135,26 +119,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));
|
||||
}
|
||||
|
||||
/** @brief Flush the pipeline
|
||||
*
|
||||
* The cpuid-instruction is used to flush the pipeline.
|
||||
*/
|
||||
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");
|
||||
}
|
||||
|
||||
/** @brief Read MSR
|
||||
*
|
||||
* The asm instruction rdmsr which stands for "Read from model specific register"
|
||||
* is used here.
|
||||
*
|
||||
* @param msr The parameter which rdmsr assumes in ECX
|
||||
* @return The value rdmsr put into EDX:EAX
|
||||
*/
|
||||
inline static uint64_t rdmsr(uint32_t msr) {
|
||||
uint32_t low, high;
|
||||
|
||||
|
@ -240,6 +204,7 @@ static inline uint32_t read_eflags(void)
|
|||
*/
|
||||
uint32_t read_eip(void);
|
||||
|
||||
<<<<<<< HEAD
|
||||
/// A one-instruction-do-nothing
|
||||
#define NOP1 asm volatile ("nop")
|
||||
/// Do nothing for 2 instructions
|
||||
|
@ -259,11 +224,16 @@ uint32_t read_eip(void);
|
|||
*
|
||||
* @return 0 in any case
|
||||
*/
|
||||
=======
|
||||
#define NOP1 asm volatile ("nop")
|
||||
#define NOP2 asm volatile ("nop;nop")
|
||||
#define NOP4 asm volatile ("nop;nop;nop;nop")
|
||||
#define NOP8 asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop")
|
||||
#define HALT asm volatile ("hlt");
|
||||
|
||||
>>>>>>> master
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -638,8 +651,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 +671,7 @@ int arch_paging_init(void)
|
|||
mmap++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Modules like the init ram disk are already loaded.
|
||||
|
@ -675,6 +690,16 @@ int arch_paging_init(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
// 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 configuration registers
|
||||
viraddr = map_region(MPB_X0_Y0, MPB_X0_Y0, (MPB_OWN-MPB_X0_Y0+16*1024*1024)/PAGE_SIZE, MAP_KERNEL_SPACE);
|
||||
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)
|
||||
|
|
|
@ -27,22 +27,23 @@
|
|||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
||||
#define CCR_INTR_ACTIVE 0x02
|
||||
|
||||
//scc_info_t scc_info;
|
||||
static char* rcce_argv[] = {"MetalSVM", "1", "533", "0"};
|
||||
/*
|
||||
* Workaround to create a suitable argv array
|
||||
*/
|
||||
static char* argv_strings[] = {"MetalSVM", "1", "533", "0"};
|
||||
static char* argv[4] = {[0 ... 3] = NULL};
|
||||
static char** rcce_argv = argv;
|
||||
static int rcce_argc = 4;
|
||||
|
||||
/*
|
||||
* 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,14 +70,12 @@ 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");
|
||||
for(i=0; i<rcce_argc; i++)
|
||||
argv[i] = argv_strings[i];
|
||||
if (RCCE_init(&rcce_argc, &rcce_argv) != RCCE_SUCCESS)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -84,59 +83,11 @@ int scc_init(void)
|
|||
num_ranks = RCCE_num_ues();
|
||||
kprintf("Got rank %d of %d ranks\n", my_rank, num_ranks);
|
||||
|
||||
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");
|
||||
|
||||
|
|
|
@ -83,6 +83,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
|
||||
*
|
||||
|
|
|
@ -111,7 +111,7 @@ int main(void)
|
|||
reschedule();
|
||||
|
||||
while(1) {
|
||||
NOP8;
|
||||
HALT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -125,7 +125,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);
|
||||
}
|
||||
|
|
@ -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