Basic page mapping, allocator, and PCI code
This commit is contained in:
parent
fea1d3e807
commit
255f560351
10
include/stdbool.h
Normal file
10
include/stdbool.h
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
#ifndef _STDBOOL_H_
|
||||
#define _STDBOOL_H_
|
||||
|
||||
#define false 0
|
||||
#define true 1
|
||||
#define bool _Bool
|
||||
|
||||
#endif /* _STDBOOL_H_ */
|
||||
|
@ -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 = [
|
||||
|
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -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__ */
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
0
sys/amd64/mp.c
Normal file
4
sys/amd64/mp.h
Normal file
4
sys/amd64/mp.h
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
uint32_t LAPIC_CPU();
|
||||
#define THISCPU LAPIC_CPU
|
||||
|
0
sys/amd64/mpboot.S
Normal file
0
sys/amd64/mpboot.S
Normal file
335
sys/amd64/pci.c
Normal file
335
sys/amd64/pci.c
Normal 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
257
sys/amd64/pmap.c
Normal 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
5
sys/amd64/pmap.h
Normal 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)
|
||||
|
@ -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) { }
|
||||
|
@ -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
74
sys/amd64/xmem.c
Normal 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
72
sys/dev/ahci.c
Normal 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
86
sys/include/pci.h
Normal 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);
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user