Merge branch 'master' into readwrite
Conflicts: arch/x86/include/asm/apic.h arch/x86/include/asm/page.h arch/x86/include/asm/processor.h arch/x86/kernel/idt.c fs/initrd.c
This commit is contained in:
commit
f730f410c3
14 changed files with 214 additions and 86 deletions
|
@ -28,28 +28,47 @@ 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
|
||||
/// Error Status Register
|
||||
#define APIC_ESR 0x0280
|
||||
/// 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 Thermal Sensor Register
|
||||
#define APIC_LVT_TSR 0x0330
|
||||
/// 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
|
||||
|
||||
#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
|
||||
/// 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_DEST_SELF 0x40000
|
||||
#define APIC_DEST_ALLINC 0x80000
|
||||
|
|
|
@ -63,6 +63,40 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Defines an IDT entry
|
||||
*
|
||||
* This structure defines interrupt descriptor table entries.\n
|
||||
* They consist of the handling function's base address, some flags
|
||||
* and a segment selector.
|
||||
*/
|
||||
typedef struct {
|
||||
/// Handler function's lower 16 address bits
|
||||
unsigned short base_lo;
|
||||
/// Handler function's segment selector.
|
||||
unsigned short sel;
|
||||
/// These bits are reserved by Intel
|
||||
unsigned char always0;
|
||||
/// These 8 bits contain flags. Exact use depends on the type of interrupt gate.
|
||||
unsigned char flags;
|
||||
/// Higher 16 bits of handler function's base address
|
||||
unsigned short base_hi;
|
||||
} __attribute__ ((packed)) idt_entry_t;
|
||||
|
||||
|
||||
/** @brief Defines the idt pointer structure.
|
||||
*
|
||||
* This structure keeps information about
|
||||
* base address and size of the interrupt descriptor table.
|
||||
*/
|
||||
typedef struct {
|
||||
/// Size of the IDT in bytes (not the number of entries!)
|
||||
unsigned short limit;
|
||||
/// Base address of the IDT
|
||||
unsigned int base;
|
||||
} __attribute__ ((packed)) idt_ptr_t;
|
||||
|
||||
|
||||
|
||||
/** @brief Installs IDT
|
||||
*
|
||||
* The installation involves the following steps:
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
#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)
|
||||
|
|
|
@ -40,6 +40,15 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
typedef struct {
|
||||
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;
|
||||
|
||||
extern bootinfo_t* bootinfo;
|
||||
|
||||
int scc_init(void);
|
||||
#endif
|
||||
|
||||
|
@ -119,6 +128,14 @@ 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 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;
|
||||
|
||||
|
@ -168,12 +185,18 @@ static inline void write_cr3(uint32_t val) {
|
|||
asm volatile("mov %0, %%cr3" : : "r"(val));
|
||||
}
|
||||
|
||||
/** @brief Read cr4 register
|
||||
* @return cr4's value
|
||||
*/
|
||||
static inline uint32_t read_cr4(void) {
|
||||
uint32_t val;
|
||||
asm volatile("mov %%cr4, %0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
/** @brief Write a value into cr4 register
|
||||
* @param val The value you want to write into cr4
|
||||
*/
|
||||
static inline void write_cr4(uint32_t val) {
|
||||
asm volatile("mov %0, %%cr4" : : "r"(val));
|
||||
}
|
||||
|
@ -181,7 +204,6 @@ static inline void write_cr4(uint32_t val) {
|
|||
/** @brief Flush a specific page entry in TLB
|
||||
* @param addr The (virtual) address of the page to flush
|
||||
*/
|
||||
|
||||
static inline void tlb_flush_one_page(uint32_t addr)
|
||||
{
|
||||
asm volatile("invlpg (%0)" : : "r"(addr) : "memory");
|
||||
|
@ -215,14 +237,25 @@ static inline uint32_t read_eflags(void)
|
|||
*/
|
||||
uint32_t read_eip(void);
|
||||
|
||||
|
||||
/// A one-instruction-do-nothing
|
||||
#define NOP1 asm volatile ("nop")
|
||||
/// Do nothing for 2 instructions
|
||||
#define NOP2 asm volatile ("nop;nop")
|
||||
/// Do nothing for 4 instructions
|
||||
#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 HALT asm volatile ("hlt");
|
||||
|
||||
|
||||
/** @brief Init several subsystems
|
||||
*
|
||||
* This function calls the initialization procedures for:
|
||||
* - GDT
|
||||
* - APIC
|
||||
* - PCI [if configured]
|
||||
*
|
||||
* @return 0 in any case
|
||||
*/
|
||||
inline static int system_init(void)
|
||||
{
|
||||
gdt_install();
|
||||
|
|
|
@ -31,38 +31,6 @@
|
|||
#include <metalsvm/string.h>
|
||||
#include <asm/idt.h>
|
||||
|
||||
/** @brief Defines an IDT entry
|
||||
*
|
||||
* This structure defines interrupt descriptor table entries.\n
|
||||
* They consist of the handling function's base address, some flags
|
||||
* and a segment selector.
|
||||
*/
|
||||
typedef struct {
|
||||
/// Handler function's lower 16 address bits
|
||||
unsigned short base_lo;
|
||||
/// Handler function's segment selector.
|
||||
unsigned short sel;
|
||||
/// These bits are reserved by Intel
|
||||
unsigned char always0;
|
||||
/// These 8 bits contain flags. Exact use depends on the type of interrupt gate.
|
||||
unsigned char flags;
|
||||
/// Higher 16 bits of handler function's base address
|
||||
unsigned short base_hi;
|
||||
} __attribute__ ((packed)) idt_entry_t;
|
||||
|
||||
|
||||
/** @brief Defines the idt pointer structure.
|
||||
*
|
||||
* This structure keeps information about
|
||||
* base address and size of the interrupt descriptor table.
|
||||
*/
|
||||
typedef struct {
|
||||
/// Size of the IDT in bytes (not the number of entries!)
|
||||
unsigned short limit;
|
||||
/// Base address of the IDT
|
||||
unsigned int base;
|
||||
} __attribute__ ((packed)) idt_ptr_t;
|
||||
|
||||
/*
|
||||
* Declare an IDT of 256 entries. Although we will only use the
|
||||
* first 32 entries in this tutorial, the rest exists as a bit
|
||||
|
@ -72,14 +40,7 @@ typedef struct {
|
|||
* "Unhandled Interrupt" exception
|
||||
*/
|
||||
static idt_entry_t idt[256] = {[0 ... 255] = {0, 0, 0, 0, 0}};
|
||||
|
||||
/** @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 ;)
|
||||
|
|
|
@ -695,6 +695,15 @@ 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);
|
||||
|
|
|
@ -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,17 +22,11 @@
|
|||
|
||||
#ifdef CONFIG_ROCKCREEK
|
||||
|
||||
bootinfo_t* bootinfo = (bootinfo_t*) SCC_BOOTINFO;
|
||||
|
||||
/* PSE bit for Pentium+ equals MPE (message buffer enable) flag in RCK! So, use it to create _PAGE_MPB symbol... */
|
||||
#define _CR4_MPE 0x00000800
|
||||
|
||||
/*
|
||||
* 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 the modified MPB program, which is part of the RCCE distribution (src/mpb.c).
|
||||
*
|
||||
|
@ -77,9 +66,13 @@ int scc_init(void)
|
|||
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)
|
||||
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();
|
||||
|
|
10
fs/initrd.c
10
fs/initrd.c
|
@ -24,6 +24,7 @@
|
|||
#include <metalsvm/errno.h>
|
||||
#include <asm/multiboot.h>
|
||||
#include <metalsvm/spinlock.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
static vfs_node_t initrd_root;
|
||||
|
||||
|
@ -227,8 +228,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;
|
||||
|
||||
|
@ -270,6 +273,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;
|
||||
|
||||
|
@ -343,6 +350,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)
|
||||
|
|
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
|
||||
|
|
Loading…
Add table
Reference in a new issue