Basic page mapping, allocator, and PCI code

This commit is contained in:
Ali Mashtizadeh 2014-06-30 15:52:35 -07:00
parent fea1d3e807
commit 255f560351
20 changed files with 1010 additions and 106 deletions

10
include/stdbool.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef _STDBOOL_H_
#define _STDBOOL_H_
#define false 0
#define true 1
#define bool _Bool
#endif /* _STDBOOL_H_ */

View File

@ -14,9 +14,12 @@ src_amd64 = [
"amd64/trap.c",
"amd64/trapentry.S",
"amd64/machine.c",
"amd64/pci.c",
"amd64/pmap.c",
"amd64/lapic.c",
"amd64/ioapic.c",
"dev/x86/vgacons.c",
"dev/ahci.c",
]
src_common = [

View File

@ -10,6 +10,9 @@
* Page Tables
*/
#define PGIDXSHIFT 9
#define PGIDXMASK (512 - 1)
#define PGSHIFT 12
#define PGSIZE (1 << PGSHIFT)
#define PGMASK (PGSIZE - 1)
@ -18,8 +21,12 @@
#define LARGE_PGSIZE (1 << LARGE_PGSHIFT)
#define LARGE_PGMASK (LARGE_PGSIZE - 1)
#define ROUNDUP_PGSIZE(x) (((x) + PGSIZE - 1) & ~PGMASK)
#define ROUNDDOWN_PGSIZE(x) ((x) & ~PGMASK)
#define HUGE_PGSHIFT 30
#define HUGE_PGSIZE (1 << HUGE_PGSHIFT)
#define HUGE_PGMASK (HUGE_PGSIZE - 1)
#define ROUNDUP_PGSIZE(x) (((x) + LARGE_PGSIZE - 1) & ~LARGE_PGMASK)
#define ROUNDDOWN_PGSIZE(x) ((x) & ~LARGE_PGMASK)
#define PTE_P 0x0001 /* Present */
#define PTE_W 0x0002 /* Writeable */
@ -36,10 +43,12 @@
#define PTE_PAT 0x1000 /* Page Attribute Table */
#define PTE_NX 0x8000000000000000ULL /* No Execute */
#define PAGETABLE_ENTRIES 512
typedef uint64_t PageEntry;
typedef struct PageTable {
PageEntry entries[512];
PageEntry entries[PAGETABLE_ENTRIES];
} PageTable;
/*

View File

@ -325,5 +325,59 @@ static INLINE void write_gs(uint16_t val)
: "r" (val));
}
static INLINE void outb(uint16_t port, uint8_t data)
{
asm volatile("outb %0, %1"
:
: "a" (data), "d" (port));
}
static INLINE void outw(uint16_t port, uint16_t data)
{
asm volatile("outw %0, %1"
:
: "a" (data), "d" (port));
}
static INLINE void outl(uint16_t port, uint32_t data)
{
asm volatile("outl %0, %1"
:
: "a" (data), "d" (port));
}
static INLINE uint8_t inb(uint16_t port)
{
uint8_t data;
asm volatile("inb %1, %0"
: "=a" (data)
:"d" (port));
return data;
}
static INLINE uint16_t inw(uint16_t port)
{
uint16_t data;
asm volatile("inw %1, %0"
: "=a" (data)
:"d" (port));
return data;
}
static INLINE uint32_t inl(uint16_t port)
{
uint32_t data;
asm volatile("inl %1, %0"
: "=a" (data)
:"d" (port));
return data;
}
#endif /* __AMD64OP_H__ */

View File

@ -21,7 +21,6 @@
#define LAPIC_EOI 0x00B0 /* End of Interrupt */
#define LAPIC_SIV 0x00F0 /* Spurious Interrupt Vector */
#define LAPIC_SIV_ENABLE 0x100
#define LAPIC_ESR 0x0280 /* Error Status Register */
#define LAPIC_LVT_TIMER 0x0320 /* LVT Timer */
#define LAPIC_LVT_TIMER_ONESHOT 0x00000000
@ -32,8 +31,6 @@
#define LAPIC_LVT_LINT0 0x0350 /* LVT LINT0 */
#define LAPIC_LVT_LINT1 0x0360 /* LVT LINT1 */
#define LAPIC_LVT_ERROR 0x0370 /* Error Register */
#define LAPIC_LVT_MASK 0x00010000
#define LAPIC_TICR 0x0380 /* Timer Initial Count Register */
#define LAPIC_TCCR 0x0390 /* Timer Currnet Count Register */
#define LAPIC_TDCR 0x03E0 /* Time Divide Configuration Register */
@ -105,18 +102,11 @@ LAPIC_Init()
LAPIC_Periodic(10000000);
LAPIC_Write(LAPIC_LVT_LINT0, LAPIC_LVT_MASK);
LAPIC_Write(LAPIC_LVT_LINT1, LAPIC_LVT_MASK);
LAPIC_Write(LAPIC_LVT_ERROR, T_IRQ_ERROR);
LAPIC_Write(LAPIC_ESR, 0);
LAPIC_Write(LAPIC_ESR, 0);
LAPIC_SendEOI();
LAPIC_Write(LAPIC_TPR, 0);
enable_interrupts();
//enable_interrupts();
}

View File

@ -80,7 +80,12 @@ void Machine_Init()
Trap_Init();
//Machine_SyscallInit();
PAlloc_AddRegion(16*1024*1024, 16*1024*1024);
PMap_Init();
LAPIC_Init();
IOAPIC_Init();
PCI_Init();
}

View File

@ -12,7 +12,6 @@
#include "amd64.h"
#include "multiboot.h"
extern void *_end;
void mbentry(unsigned long magic, unsigned long addr);
@ -25,37 +24,28 @@ extern void Machine_Init();
extern void PAlloc_Init();
extern void PAlloc_AddRegion(uintptr_t start, uintptr_t len);
#define GENTBL_2(base) (base + 0x183), (base + 0x200183),
#define GENTBL_8(base) GENTBL_2(base) GENTBL_2(base + 0x400000) \
GENTBL_2(base + 0x800000) GENTBL_2(base + 0xC00000)
#define GENTBL_32(base) GENTBL_8(base) GENTBL_8(base + 0x1000000) \
GENTBL_8(base + 0x2000000) GENTBL_8(base + 0x3000000)
#define GENTBL_128(base) GENTBL_32(base) GENTBL_32(base + 0x4000000) \
GENTBL_32(base + 0x8000000) GENTBL_32(base + 0xC000000)
#define GENTBL(base) GENTBL_128(base) GENTBL_128(base + 0x10000000) \
GENTBL_128(base + 0x20000000) GENTBL_128(base + 0x30000000)
PAGE_ALIGN DATA_SECTION PageTable bootpgtbl3a = { .entries = {
GENTBL(0x0)
}};
PAGE_ALIGN DATA_SECTION PageTable bootpgtbl3b = { .entries = {
GENTBL(0x40000000)
}};
PAGE_ALIGN DATA_SECTION PageTable bootpgtbl3c = { .entries = {
GENTBL(0x80000000)
}};
PAGE_ALIGN DATA_SECTION PageTable bootpgtbl3d = { .entries = {
GENTBL(0xC0000000)
PAGE_ALIGN DATA_SECTION PageTable bootpgtbl3 = { .entries = {
0x0000000000000183,
0x0000000000200183,
0x0000000000400183,
0x0000000000600183,
0x0000000000800183,
0x0000000000A00183,
0x0000000000C00183,
0x0000000000E00183,
0x0000000001000183,
0x0000000001200183,
0x0000000001400183,
0x0000000001600183,
0x0000000001800183,
0x0000000001A00183,
0x0000000001C00183,
0x0000000001E00183,
0x0000000002000183,
}};
PAGE_ALIGN DATA_SECTION PageTable bootpgtbl2 = { .entries = {
(uint64_t)&bootpgtbl3a + 0x03,
(uint64_t)&bootpgtbl3b + 0x03,
(uint64_t)&bootpgtbl3c + 0x03,
(uint64_t)&bootpgtbl3d + 0x03,
(uint64_t)&bootpgtbl3 + 0x03,
0
}};
@ -165,10 +155,7 @@ mb_entry(unsigned long magic, unsigned long addr)
Machine_Init();
uint64_t memoryStart = (uintptr_t)&_end;
PAlloc_Init();
return;
/* @r{Are mmap_* valid?} */
if (CHECK_FLAG (mbi->flags, 6))
{
@ -189,24 +176,11 @@ mb_entry(unsigned long magic, unsigned long addr)
uintptr_t start = mmap->addr;
uintptr_t len = mmap->len;
if (start + len > memoryStart)
{
if (start < memoryStart)
{
len = len - (memoryStart - start);
start = memoryStart;
}
if ((len % PGSIZE) != 0)
len = len - len % PGSIZE;
if ((start % PGSIZE) != 0)
{
len = len - (PGSIZE - (start & PGMASK));
start = ROUNDUP_PGSIZE(start);
}
len = ROUNDDOWN_PGSIZE(len);
PAlloc_AddRegion(start, len);
}
// XXX: Fix me to skip kernel
PAlloc_AddRegion(start, len);
}
}
}

0
sys/amd64/mp.c Normal file
View File

4
sys/amd64/mp.h Normal file
View File

@ -0,0 +1,4 @@
uint32_t LAPIC_CPU();
#define THISCPU LAPIC_CPU

0
sys/amd64/mpboot.S Normal file
View File

335
sys/amd64/pci.c Normal file
View File

@ -0,0 +1,335 @@
#include <stdint.h>
#include <kassert.h>
#include <pci.h>
#include "amd64.h"
#include "amd64op.h"
void PCI_ScanBus();
void
PCI_Init()
{
kprintf("Initializing PCI\n");
PCI_ScanBus();
kprintf("PCI Initialization Done\n");
}
#define PCI_PORT_ADDR 0xCF8
#define PCI_PORT_DATABASE 0xCFC
static inline uint32_t
PCIGetAddr(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
{
ASSERT(bus < 256 && slot < 64 && func < 8 && reg < 256);
return (1 << 31) | (bus << 16) | (slot << 11) | (func << 8) | (reg & 0x00fc);
}
uint8_t
PCICfgRead8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
{
uint32_t addr = PCIGetAddr(bus, slot, func, reg);
uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
outl(PCI_PORT_ADDR, addr);
return inb(port);
}
uint16_t
PCICfgRead16(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
{
uint32_t addr = PCIGetAddr(bus, slot, func, reg);
uint16_t port = PCI_PORT_DATABASE + (reg & 0x2);
ASSERT((reg & 0x1) == 0);
outl(PCI_PORT_ADDR, addr);
return inw(port);
}
uint32_t
PCICfgRead32(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg)
{
uint32_t addr = PCIGetAddr(bus, slot, func, reg);
uint16_t port = PCI_PORT_DATABASE;
ASSERT((reg & 0x3) == 0);
outl(PCI_PORT_ADDR, addr);
return inl(port);
}
void
PCICfgWrite8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg,
uint8_t data)
{
uint32_t addr = PCIGetAddr(bus, slot, func, reg);
uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
outl(PCI_PORT_ADDR, addr);
outb(port, data);
}
void
PCICfgWrite16(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg,
uint16_t data)
{
uint32_t addr = PCIGetAddr(bus, slot, func, reg);
uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
outl(PCI_PORT_ADDR, addr);
outw(port, data);
}
void
PCICfgWrite32(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg,
uint32_t data)
{
uint32_t addr = PCIGetAddr(bus, slot, func, reg);
uint16_t port = PCI_PORT_DATABASE + (reg & 0x3);
outl(PCI_PORT_ADDR, addr);
outl(port, data);
}
uint16_t
PCIGetDeviceID(uint32_t bus, uint32_t device, uint32_t func)
{
return PCICfgRead16(bus, device, func, PCI_OFFSET_DEVICEID);
}
uint16_t
PCIGetVendorID(uint32_t bus, uint32_t device, uint32_t func)
{
return PCICfgRead16(bus, device, func, PCI_OFFSET_VENDORID);
}
uint8_t
PCIGetBaseClass(uint32_t bus, uint32_t device, uint32_t func)
{
return PCICfgRead8(bus, device, func, PCI_OFFSET_CLASS);
}
uint8_t
PCIGetSubClass(uint32_t bus, uint32_t device, uint32_t func)
{
return PCICfgRead8(bus, device, func, PCI_OFFSET_SUBCLASS);
}
uint8_t
PCIGetHeaderType(uint32_t bus, uint32_t device, uint32_t func)
{
return PCICfgRead8(bus, device, func, PCI_OFFSET_HEADERTYPE);
}
uint8_t
PCI_CfgRead8(PCIDevice *dev, uint32_t reg)
{
return PCICfgRead8(dev->bus, dev->slot, dev->func, reg);
}
uint16_t
PCI_CfgRead16(PCIDevice *dev, uint32_t reg)
{
return PCICfgRead16(dev->bus, dev->slot, dev->func, reg);
}
uint32_t
PCI_CfgRead32(PCIDevice *dev, uint32_t reg)
{
return PCICfgRead32(dev->bus, dev->slot, dev->func, reg);
}
void
PCI_CfgWrite8(PCIDevice *dev, uint32_t reg, uint8_t data)
{
return PCICfgWrite8(dev->bus, dev->slot, dev->func, reg, data);
}
void
PCI_CfgWrite16(PCIDevice *dev, uint32_t reg, uint16_t data)
{
return PCICfgWrite16(dev->bus, dev->slot, dev->func, reg, data);
}
void
PCI_CfgWrite32(PCIDevice *dev, uint32_t reg, uint32_t data)
{
return PCICfgWrite32(dev->bus, dev->slot, dev->func, reg, data);
}
uint16_t
PCI_GetDeviceID(PCIDevice *dev)
{
return PCI_CfgRead16(dev, PCI_OFFSET_DEVICEID);
}
uint16_t
PCI_GetVendorID(PCIDevice *dev)
{
return PCI_CfgRead16(dev, PCI_OFFSET_VENDORID);
}
uint8_t
PCI_GetBaseClass(PCIDevice *dev)
{
return PCI_CfgRead8(dev, PCI_OFFSET_CLASS);
}
uint8_t
PCI_GetSubClass(PCIDevice *dev)
{
return PCI_CfgRead8(dev, PCI_OFFSET_SUBCLASS);
}
uint8_t
PCI_GetHeaderType(PCIDevice *dev)
{
return PCI_CfgRead8(dev, PCI_OFFSET_HEADERTYPE);
}
void
PCICheckFunction(uint32_t bus, uint32_t device, uint32_t func)
{
uint8_t baseClass, subClass;
uint16_t vendorId, deviceId;
baseClass = PCIGetBaseClass(bus, device, func);
subClass = PCIGetSubClass(bus, device, func);
vendorId = PCIGetVendorID(bus, device, func);
deviceId = PCIGetDeviceID(bus, device, func);
if ((baseClass == PCI_CLASS_BRIDGE) && (subClass == 0x00)) {
kprintf("PCI(%d,%d,%d): Host Bridge (%04x:%04x)\n",
bus, device, func, vendorId, deviceId);
} else if ((baseClass == PCI_CLASS_BRIDGE) && (subClass == 0x01)) {
kprintf("PCI(%d,%d,%d): ISA Bridge (%04x:%04x)\n",
bus, device, func, vendorId, deviceId);
} else if ((baseClass == PCI_CLASS_BRIDGE) && (subClass == 0x04)) {
kprintf("PCI(%d,%d,%d): PCI-PCI Bridge (%04x:%04x)\n",
bus, device, func, vendorId, deviceId);
// uint8_t subBus = getSecondaryBus(bus, device, func);
// PCIScanBus(subBus);
} else if ((baseClass == PCI_CLASS_STORAGE) && (subClass == PCI_SCLASS_STORAGE_SATA)) {
kprintf("PCI(%d,%d,%d): SATA Controller (%04x:%04x)\n",
bus, device, func, vendorId, deviceId);
AHCI_Init(bus, device, func);
} else if ((baseClass == PCI_CLASS_NETWORK) && (subClass == 0x00)) {
kprintf("PCI(%d,%d,%d): Ethernet (%04x:%04x)\n",
bus, device, func, vendorId, deviceId);
} else if ((baseClass == PCI_CLASS_GRAPHICS) && (subClass == 0x00)) {
kprintf("PCI(%d,%d,%d): VGA (%04x:%04x)\n",
bus, device, func, vendorId, deviceId);
} else if ((baseClass == PCI_CLASS_BUS) && (subClass == PCI_SCLASS_BUS_SMBUS)) {
kprintf("PCI(%d,%d,%d): SMBUS (%04x:%04x)\n",
bus, device, func, vendorId, deviceId);
} else {
kprintf("PCI(%d,%d,%d): Unsupported (%04x:%04x %02x:%02x)\n",
bus, device, func, vendorId, deviceId, baseClass, subClass);
}
}
void
PCIScanDevice(uint32_t bus, uint32_t device)
{
uint8_t headerType;
uint16_t vendorId;
vendorId = PCIGetVendorID(bus, device, 0);
if (vendorId == 0xFFFF)
return;
PCICheckFunction(bus, device, 0);
headerType = PCIGetHeaderType(bus, device, 0);
if ((headerType & 0x80) != 0) {
uint8_t func;
for (func = 0; func < 8; func++) {
if (PCIGetVendorID(bus, device, func) != 0xFFFF) {
PCICheckFunction(bus, device, func);
}
}
}
}
void
PCIScanBus(uint8_t bus)
{
uint8_t device;
for (device = 0; device < 32; device++) {
PCIScanDevice(bus, device);
}
}
void
PCI_ScanBus()
{
uint8_t headerType = PCIGetHeaderType(0, 0, 0);
if ((headerType & 0x80) == 0) {
PCIScanBus(0);
} else {
uint8_t busNo;
for (busNo = 0; busNo < 8; busNo++) {
if (PCIGetVendorID(0, 0, busNo) != 0xFFFF)
break;
PCIScanBus(busNo);
}
}
}
void
PCI_Configure(PCIDevice *dev)
{
int bar;
dev->irq = PCI_CfgRead8(dev, PCI_OFFSET_IRQLINE);
PCI_CfgWrite16(dev, PCI_OFFSET_COMMAND,
PCI_COMMAND_IOENABLE | PCI_COMMAND_MEMENABLE | PCI_COMMAND_BUSMASTER);
for (bar = 0; bar < PCI_MAX_BARS; bar++)
{
dev->bars[bar].base = 0;
dev->bars[bar].size = 0;
dev->bars[bar].type = PCIBAR_TYPE_NULL;
}
for (bar = 0; bar < PCI_MAX_BARS; bar++)
{
uint32_t barReg = PCI_OFFSET_BARFIRST + 4 * bar;
uint32_t base, size;
uint32_t origValue = PCI_CfgRead32(dev, barReg);
PCI_CfgWrite32(dev, barReg, 0xFFFFFFFF);
size = PCI_CfgRead32(dev, barReg);
if (size == 0)
continue;
PCI_CfgWrite32(dev, barReg, origValue);
if (origValue & 0x1)
{
dev->bars[bar].type = PCIBAR_TYPE_IO;
base = origValue & 0xFFFFFFFC;
size = size & 0xFFFFFFFC;
size = ~size + 1;
} else {
dev->bars[bar].type = PCIBAR_TYPE_MEM;
base = origValue & 0xFFFFFFF0;
size = size & 0xFFFFFFF0;
size = ~size + 1;
// XXX: Support 64-bit
ASSERT((origValue & 0x06) == 0x00);
}
dev->bars[bar].base = base;
dev->bars[bar].size = size;
}
}

257
sys/amd64/pmap.c Normal file
View File

@ -0,0 +1,257 @@
#include <stdbool.h>
#include <stdint.h>
#include <kconfig.h>
#include <kassert.h>
#include "amd64.h"
#include "amd64op.h"
#include "mp.h"
typedef struct AS
{
PageTable *root;
uint64_t tables;
uint64_t mappings;
} AS;
AS systemAS;
AS *currentAS[MAX_CPUS];
bool PMap_SystemLMap(uint64_t phys, uint64_t virt, uint64_t lpages);
void PMapDump(AS *space);
void
PMap_Init()
{
int i, j;
kprintf("Initializing PMAP ... ");
// Setup global state
for (i = 0; i < MAX_CPUS; i++) {
currentAS[i] = 0;
}
// Allocate system page table
systemAS.root = PAlloc_AllocPage();
systemAS.tables = PAGETABLE_ENTRIES / 2 + 1;
systemAS.mappings = 0;
if (!systemAS.root)
PANIC("Cannot allocate system page table");
for (i = PAGETABLE_ENTRIES / 2; i < PAGETABLE_ENTRIES; i++) {
PageTable *pgtbl = PAlloc_AllocPage();
PageEntry pte = (uint64_t)pgtbl | PTE_W | PTE_P;
if (!pgtbl)
PANIC("Not enough memory!");
systemAS.root->entries[i] = pte;
// XXX: Hack for now
systemAS.root->entries[i - PAGETABLE_ENTRIES / 2] = pte;
for (j = 0; j < PAGETABLE_ENTRIES; j++) {
pgtbl->entries[j] = 0;
}
}
// Setup system mappings
// XXX XXX XXX
PMap_SystemLMap(0x0, 0x0, 0x100000000ULL >> LARGE_PGSHIFT);
//PMapDump(&systemAS);
write_cr3((uint64_t)systemAS.root);
kprintf("Done!\n");
}
AS*
Map_NewAS()
{
int i;
AS *as = PAlloc_AllocPage();
if (!as)
return 0;
as->root = PAlloc_AllocPage();
as->tables = 1;
as->mappings = 0;
if (!as->root) {
PAlloc_FreePage(as);
return 0;
}
for (i = 0; i < PAGETABLE_ENTRIES; i++)
{
as->root->entries[i] = 0;
}
return as;
}
void
PMap_DestroyAS(AS *space)
{
}
void
PMap_LoadAS(AS *space)
{
write_cr3((uint64_t)space->root);
currentAS[THISCPU()] = space;
}
PageTable *
PMapAllocPageTable()
{
int i;
PageTable *pgtbl = PAlloc_AllocPage();
if (!pgtbl)
return 0;
for (i = 0; i < PAGETABLE_ENTRIES; i++) {
pgtbl->entries[i] = 0;
}
return pgtbl;
}
void
PMapLookupEntry(AS *space, uint64_t va, PageEntry **entry, int size)
{
int i,j,k,l;
PageTable *table = space->root;
PageEntry pte;
i = (va >> (HUGE_PGSHIFT + PGIDXSHIFT)) & PGIDXMASK;
j = (va >> HUGE_PGSHIFT) & PGIDXMASK;
k = (va >> LARGE_PGSHIFT) & PGIDXMASK;
l = (va >> PGSHIFT) & PGIDXMASK;
*entry = NULL;
pte = table->entries[i];
if (pte == 0) {
PageTable *newtable = PMapAllocPageTable();
if (!newtable)
return;
pte = (uint64_t)newtable | PTE_P | PTE_W;
table->entries[i] = pte;
}
table = (PageTable *)(pte & 0xFFFFFFFFFFFFF000);
pte = table->entries[j];
if (pte == 0) {
PageTable *newtable = PMapAllocPageTable();
if (!newtable)
return;
pte = (uint64_t)newtable | PTE_P | PTE_W;
table->entries[j] = pte;
}
if (size == HUGE_PGSIZE) {
// Handle 1GB pages
*entry = &table->entries[j];
return;
}
table = (PageTable *)(pte & 0xFFFFFFFFFFFFF000);
pte = table->entries[k];
if (pte == 0) {
PageTable *newtable = PMapAllocPageTable();
if (!newtable)
return;
pte = (uint64_t)newtable | PTE_P | PTE_W;
table->entries[k] = pte;
}
if (size == LARGE_PGSIZE) {
// Handle 2MB pages
*entry = &table->entries[k];
return;
}
table = (PageTable *)(pte & 0xFFFFFFFFFFFFF000);
// Handle 4KB pages
ASSERT(size == PGSIZE);
*entry = &table->entries[l];
return;
}
void
PMapDump(AS *space)
{
int i,j,k;
PageTable *root = space->root;
kprintf("Root: %08llx\n", (uint64_t)space->root);
for (i = 0; i < PAGETABLE_ENTRIES; i++) {
PageEntry pte = root->entries[i];
PageTable *l1 = (PageTable *)(pte & 0xFFFFFFFFFFFFF000);
if (!(pte & PTE_P))
continue;
kprintf("Level 1: %08llx\n", (uint64_t)pte);
for (j = 0; j < PAGETABLE_ENTRIES; j++) {
PageEntry pte = l1->entries[i];
PageTable *l2 = (PageTable *)(pte & 0xFFFFFFFFFFFFF000);
if (!(pte & PTE_P))
continue;
kprintf("Level 2: %08llx\n", (uint64_t)pte);
for (k = 0; k < PAGETABLE_ENTRIES; k++) {
PageEntry pte = l2->entries[i];
PageTable *l3 = (PageTable *)(pte & 0xFFFFFFFFFFFFF000);
if (!(pte & PTE_P))
continue;
kprintf("Level 3: %08llx\n", (uint64_t)pte);
}
}
}
return;
}
bool
PMap_SystemLMap(uint64_t phys, uint64_t virt, uint64_t lpages)
{
int i;
PageEntry *entry;
for (i = 0; i < lpages; i++) {
uint64_t va = virt + LARGE_PGSIZE * i;
PMapLookupEntry(&systemAS, va, &entry, LARGE_PGSIZE);
if (!entry) {
kprintf("SystemLMap failed to allocate memory!\n");
return false;
}
*entry = (phys + LARGE_PGSIZE * i) | PTE_P | PTE_W | PTE_PS;
//kprintf("SystemLMap VA: %08x, PTE: %08x\n", va, *entry);
}
return true;
}
bool
PMap_SystemMap(uint64_t phys, uint64_t virt, uint64_t pages)
{
}
bool
PMap_SystemUnmap(uint64_t virt, uint64_t pages)
{
}

5
sys/amd64/pmap.h Normal file
View File

@ -0,0 +1,5 @@
#define MEM_DIRECTMAP_BASE 0x0000000000000000ULL
#define PPN2DMVA(ppn) (((ppn) << PGSIZE) + MEM_DIRECTMAP_BASE)
#define DMVA2PPN(dmva) (((dmva) - MEM_DIRECTMAP_BASE) >> PGSIZE)

View File

@ -111,15 +111,12 @@ trap_entry(TrapFrame *tf)
if (tf->vector >= T_IRQ_BASE && tf->vector <= T_IRQ_MAX)
{
kprintf("IRQ: %d\n", tf->vector);
LAPIC_SendEOI();
return;
}
if (tf->vector == T_IRQ_SPURIOUS)
{
kprintf("Spurious interrupt!");
LAPIC_SendEOI();
}
trap_dump(tf);
while (1) { }

View File

@ -32,7 +32,6 @@
#define T_IRQ_KBD (T_IRQ_BASE + 1)
#define T_IRQ_COM1 (T_IRQ_BASE + 4)
#define T_IRQ_SPURIOUS (T_IRQ_BASE + 24)
#define T_IRQ_ERROR (T_IRQ_BASE + 25)
#define T_MAX 64

74
sys/amd64/xmem.c Normal file
View File

@ -0,0 +1,74 @@
#include <stdbool.h>
#include <stdint.h>
#include <kconfig.h>
#include <kassert.h>
#include "amd64.h"
#include "amd64op.h"
#include "mp.h"
#define MAX_XMEM_REGIONS 1024
typedef struct XMem
{
bool inUse;
uint64_t base;
uint64_t maxLength;
uint64_t length;
};
XMem regions[MAX_XMEM_REGIONS];
void
XMem_Init()
{
kprintf("Initializing XMEM ... ");
kprintf("Done!\n");
}
XMem *
XMem_New()
{
return NULL;
}
void
XMem_Destroy(XMem *xmem)
{
}
uint64_t
XMem_GetBase(XMem *xmem)
{
return xmem->base;
}
uint64_t
XMem_GetLength(XMem *xmem)
{
return xmem->length;
}
bool
XMem_Allocate(XMem *xmem, uint64_t length)
{
}
bool
XMem_Shrink(XMem *xmem, uint64_t length)
{
}
bool
XMem_Map(XMem *xmem, uint64_t phys, uint64_t off, uint64_t length)
{
}
void
XMem_Unmap(XMem *xmem, uint64_t off, uint64_t length)
{
}

72
sys/dev/ahci.c Normal file
View File

@ -0,0 +1,72 @@
#include <stdint.h>
#include <kassert.h>
#include <pci.h>
typedef struct AHCIDevice
{
uint32_t device;
const char *name;
uint32_t flags;
} AHCIDevice;
static AHCIDevice deviceList[] =
{
{ 0x80862922, "ICH9", 0 },
{ 0, "", 0 },
};
void AHCI_Configure(PCIDevice dev);
void
AHCI_Init(uint32_t bus, uint32_t slot, uint32_t func)
{
PCIDevice dev;
dev.bus = bus;
dev.slot = slot;
dev.func = func;
dev.vendor = PCI_GetVendorID(&dev);
dev.device = PCI_GetDeviceID(&dev);
uint32_t device = dev.vendor << 16 | dev.device;
uint8_t progif = PCI_CfgRead8(&dev, PCI_OFFSET_PROGIF);
if (progif != 0x01)
{
kprintf("Unsupported SATA Controller PROGIF=%02x\n", progif);
return;
}
int deviceIdx = 0;
while (deviceList[deviceIdx].device != 0x0) {
if (deviceList[deviceIdx].device == device) {
kprintf("AHCI: Found %s\n", deviceList[deviceIdx].name);
// Configure and add disks
AHCI_Configure(dev);
}
deviceIdx++;
}
}
void
AHCI_Configure(PCIDevice dev)
{
PCI_Configure(&dev);
kprintf("AHCI: IRQ %d\n", dev.irq);
// MMIO
int bar;
for (bar = 0; bar < PCI_MAX_BARS; bar++) {
if (dev.bars[bar].size == 0)
continue;
kprintf("AHCI: BAR%d base=%08x size=%08x %s\n",
bar, dev.bars[bar].base, dev.bars[bar].size,
dev.bars[bar].type == PCIBAR_TYPE_IO ? "IO" : "Mem");
}
}

86
sys/include/pci.h Normal file
View File

@ -0,0 +1,86 @@
#define PCI_OFFSET_VENDORID 0x00
#define PCI_OFFSET_DEVICEID 0x02
#define PCI_OFFSET_COMMAND 0x04
#define PCI_OFFSET_STATUS 0x06
#define PCI_OFFSET_REVISIONID 0x08
#define PCI_OFFSET_PROGIF 0x09
#define PCI_OFFSET_SUBCLASS 0x0A
#define PCI_OFFSET_CLASS 0x0B
#define PCI_OFFSET_CACHELINE 0x0C
#define PCI_OFFSET_LATENCYTMR 0x0D
#define PCI_OFFSET_HEADERTYPE 0x0E
#define PCI_OFFSET_BIST 0x0F
#define PCI_OFFSET_BARFIRST 0x10
#define PCI_OFFSET_BARLAST 0x24
#define PCI_OFFSET_IRQLINE 0x3C
#define PCI_COMMAND_IOENABLE 0x0001
#define PCI_COMMAND_MEMENABLE 0x0002
#define PCI_COMMAND_BUSMASTER 0x0004
#define PCI_MAX_BARS 6
#define PCI_CLASS_STORAGE 0x01
#define PCI_CLASS_NETWORK 0x02
#define PCI_CLASS_GRAPHICS 0x03
#define PCI_CLASS_BRIDGE 0x06
#define PCI_CLASS_BUS 0x0C
#define PCI_SCLASS_STORAGE_SATA 0x06
#define PCI_SCLASS_BUS_FW 0x00
#define PCI_SCLASS_BUS_USB 0x03
#define PCI_SCLASS_BUS_SMBUS 0x05
#define PCIBAR_TYPE_NULL 0
#define PCIBAR_TYPE_IO 1
#define PCIBAR_TYPE_MEM 2
typedef struct PCIBAR
{
uint32_t base;
uint32_t size;
uint32_t type;
} PCIBAR;
typedef struct PCIDevice
{
uint16_t vendor;
uint16_t device;
uint8_t bus;
uint8_t slot;
uint8_t func;
uint8_t irq;
PCIBAR bars[PCI_MAX_BARS];
} PCIDevice;
void PCI_Init();
/*
uint8_t PCICfgRead8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg);
uint16_t PCICfgRead16(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg);
uint32_t PCICfgRead32(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg);
void PCICfgWrite8(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg, uint8_t data);
void PCICfgWrite16(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg, uint16_t data);
void PCICfgWrite32(uint32_t bus, uint32_t slot, uint32_t func, uint32_t reg, uint32_t data);
*/
uint8_t PCI_CfgRead8(PCIDevice *dev, uint32_t reg);
uint16_t PCI_CfgRead16(PCIDevice *dev, uint32_t reg);
uint32_t PCI_CfgRead32(PCIDevice *dev, uint32_t reg);
void PCI_CfgWrite8(PCIDevice *dev, uint32_t reg, uint8_t data);
void PCI_CfgWrite16(PCIDevice *dev, uint32_t reg, uint16_t data);
void PCI_CfgWrite32(PCIDevice *dev, uint32_t reg, uint32_t data);
uint16_t PCI_GetDeviceID(PCIDevice *dev);
uint16_t PCI_GetVendorID(PCIDevice *dev);
uint8_t PCI_GetBaseClass(PCIDevice *dev);
uint8_t PCI_GetSubClass(PCIDevice *dev);
uint8_t PCI_GetHeaderType(PCIDevice *dev);
void PCI_Configure(PCIDevice *dev);

View File

@ -8,35 +8,53 @@
#include <kassert.h>
void palloc_init()
typedef struct TLSFBlock
{
struct TLSFBlock *prevBlock;
uint64_t size;
// Only valid for free blocks
struct TLSFBlock *prev;
struct TLSFBlock *next;
} TLSFBlock;
typedef struct Heap
{
uint64_t magic;
// Lock
// Debug statistics
uint64_t poolSize;
uint64_t poolAllocs;
// Free list
uint32_t flVector;
uint32_t slVector[FL_SIZE];
struct TLSFBlock *blocks[SL_SIZE][FL_SIZE];
} Heap;
Heap*
Malloc_Create()
{
}
void palloc_add_region(uintptr_t start, uintptr_t len)
void
Malloc_Destroy(Heap *heap)
{
}
void *palloc_alloc(uintptr_t len)
void*
Malloc_Alloc(Heap *heap, uint64_t len)
{
}
void palloc_free(void *region)
void
Malloc_Free(Heap *heap, void *buf)
{
}
void *palloc_alloc_lpage()
{
}
void palloc_free_lpage(void *lpg)
{
}
void *palloc_alloc_page()
{
}
void palloc_free_page(void *pg)
bool
Malloc_Realloc(Heap *heap, void *buf, uint64_t newlen)
{
}

View File

@ -12,25 +12,31 @@
#include "../amd64/amd64.h"
/* 'FREEPAGE' */
#define FREEPAGE_MAGIC_FREE 0x4652454550414745ULL
/* 'ALLOCATE' */
#define FREEPAGE_MAGIC_INUSE 0x414c4c4f43415445ULL
typedef struct FreePage
{
TAILQ_ENTRY(FreePage) entries;
uint64_t magic;
LIST_ENTRY(FreePage) entries;
} FreePage;
TAILQ_HEAD(FreeListHead, FreePage) freeList;
LIST_HEAD(FreeListHead, FreePage) freeList;
void PAlloc_Init()
void
PAlloc_Init()
{
TAILQ_INIT(&freeList);
LIST_INIT(&freeList);
}
void PAlloc_AddRegion(uintptr_t start, uintptr_t len)
void
PAlloc_AddRegion(uintptr_t start, uintptr_t len)
{
uintptr_t i;
FreePage *pg;
kprintf("PAlloc_AddRegion(%08llx, %08llx)\n", start, len);
if ((start % PGSIZE) != 0)
Panic("Region start is not page aligned!");
if ((len % PGSIZE) != 0)
@ -39,29 +45,35 @@ void PAlloc_AddRegion(uintptr_t start, uintptr_t len)
for (i = 0; i < len; i += PGSIZE)
{
pg = (void *)(start + i);
TAILQ_INSERT_TAIL(&freeList, pg, entries);
pg->magic = FREEPAGE_MAGIC_FREE;
LIST_INSERT_HEAD(&freeList, pg, entries);
}
}
void *PAlloc_AllocPage()
void *
PAlloc_AllocPage()
{
FreePage *pg = TAILQ_FIRST(&freeList);
FreePage *pg = LIST_FIRST(&freeList);
LIST_REMOVE(pg, entries);
TAILQ_REMOVE(&freeList, pg, entries);
// Assert page aligned
ASSERT((((uintptr_t)pg) & PGMASK) == 0);
ASSERT(pg->magic == FREEPAGE_MAGIC_FREE);
pg->magic = FREEPAGE_MAGIC_INUSE;
//kprintf("PAlloc_AllocPage: %08llx\n", pg);
return (void *)pg;
}
void PAlloc_FreePage(void *region)
void
PAlloc_FreePage(void *region)
{
FreePage *pg = (FreePage *)region;
LIST_INSERT_HEAD(&freeList, pg, entries);
// Assert page aligned
ASSERT((((uintptr_t)region) & PGMASK) == 0);
TAILQ_INSERT_HEAD(&freeList, pg, entries);
#ifndef NDEBUG
// Application can write this magic, but for
// debug builds we can use this as a double free check.
ASSERT(pg->magic != FREEPAGE_MAGIC_FREE);
#endif
pg->magic = FREEPAGE_MAGIC_FREE;
}