Merge branch 'master' into readwrite

Conflicts:
	.gitignore
	arch/x86/include/asm/apic.h
	arch/x86/include/asm/processor.h
This commit is contained in:
Marian Ohligs 2011-04-08 16:25:00 +02:00
commit b6079272c1
15 changed files with 313 additions and 251 deletions

View file

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

View file

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

View file

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

View file

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

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

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

View file

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

View file

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

View file

@ -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
*

View file

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

View file

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

View file

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

View file

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