added an untested pmm for every machine except for PC
This commit is contained in:
parent
d0736af522
commit
8f9423b5cd
20 changed files with 384 additions and 30 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -16,3 +16,5 @@ latex/
|
|||
int.s
|
||||
regs.h
|
||||
out/
|
||||
*.mmap
|
||||
*.mh
|
||||
|
|
78
buildtools/mmapcomp.py
Executable file
78
buildtools/mmapcomp.py
Executable file
|
@ -0,0 +1,78 @@
|
|||
#!/usr/bin/env python3
|
||||
import sys,os
|
||||
sf = sys.argv[1]
|
||||
tf = os.path.splitext(sf)[0] + ".mmap"
|
||||
hf = os.path.splitext(sf)[0] + ".mh"
|
||||
with open(sf) as f:
|
||||
code = [ x[:-1] for x in f.readlines()]
|
||||
obj = []
|
||||
endian='little'
|
||||
bits=32
|
||||
for line in code:
|
||||
data = b''
|
||||
a = line.split(' ')
|
||||
if a[0] == "DEVICETYPE":
|
||||
data+=b'\x00'
|
||||
data+=b'\x01'
|
||||
devicetypes={"PC":b'\x00', "CONSOLE":b'\x01', "EMBEDDED":b'\x02'}
|
||||
data+=devicetypes[a[1]]
|
||||
elif a[0] == "DEVICENAME":
|
||||
data+=b'\x01'
|
||||
data+=len(a[1]).to_bytes(1,'little')
|
||||
data+=a[1].encode("UTF-8")
|
||||
elif a[0] == "CPUARCH":
|
||||
data+=b'\x02'
|
||||
data+=b'\x01'
|
||||
archs = {"X86":b'\x00', "X86_64":b'\x01', "ARM":b'\x02'}
|
||||
data+=archs[a[1]]
|
||||
elif a[0] == "ENDIAN":
|
||||
data+=b'\x03'
|
||||
data+=b'\x01'
|
||||
if a[1] == "BIG":
|
||||
data+=b'\x00'
|
||||
endian='big'
|
||||
else:
|
||||
data+=b'\x01'
|
||||
endian="little"
|
||||
elif a[0] == "BITS":
|
||||
data+=b'\x04'
|
||||
data+=b'\x01'
|
||||
if a[1] == "32":
|
||||
data+=b'\x20'
|
||||
bits=32
|
||||
else:
|
||||
data+=b'\x40'
|
||||
bits=64
|
||||
elif a[0] == "REGION":
|
||||
data+=b'\x05'
|
||||
data+=(bits//4+1).to_bytes(1,endian)
|
||||
data+=int(a[1],16).to_bytes(bits//8,endian)
|
||||
data+=int(a[2],16).to_bytes(bits//8,endian)
|
||||
perms={
|
||||
"NONE": 0,
|
||||
"X": 1,
|
||||
"W": 2,
|
||||
"WX": 3,
|
||||
"R": 4,
|
||||
"RX": 5,
|
||||
"RW": 6,
|
||||
"RWX": 7
|
||||
}
|
||||
data+=perms[a[3]].to_bytes(1,endian)
|
||||
elif a[0] == "":
|
||||
continue
|
||||
else:
|
||||
raise ValueError("Unknown command '"+a[0]+"'")
|
||||
obj.append(data)
|
||||
mmdata = b'MMAP' + bytes(4) + len(obj).to_bytes(4,'little')
|
||||
for o in obj:
|
||||
mmdata += o
|
||||
with open(tf,"wb") as f:
|
||||
f.write(mmdata)
|
||||
with open(hf, "w") as f:
|
||||
f.write("#pragma once\n")
|
||||
f.write("#include <stdint.h>\n")
|
||||
f.write("uint8_t mmap[] = {\n")
|
||||
for b in mmdata:
|
||||
f.write(hex(b)+", ")
|
||||
f.write("\n};\n")
|
95
docs/mmap.md
Normal file
95
docs/mmap.md
Normal file
|
@ -0,0 +1,95 @@
|
|||
# Memory Map File Format
|
||||
## .mc - Clear text Memory Map
|
||||
| Identifier | Meaning |
|
||||
|------------|----------------------------------------------------------|
|
||||
|`DEVICETYPE`|Type of the device. One of `PC`, `CONSOLE` and `EMBEDDED` |
|
||||
|`DEVICENAME`|Pascal strings containing the name of the device |
|
||||
|`CPUARCH` | Architecture. Currently one of `X86`, `X86_64` and `ARM` |
|
||||
|`ENDIAN` | `BIG` or `LITTLE` |
|
||||
|`BITS` | `32` or `64` |
|
||||
|`REGION` | A region of Memory. Arguments are `START_ADDR`, `END_ADDR`, and `PERMISSIONS` (`R`, `RW`, `RX`, `RWX`) Only memory with `RWX` permissions can be allocated. |
|
||||
|
||||
Example:
|
||||
|
||||
DEVICETYPE CONSOLE
|
||||
DEVICENAME 3DS9
|
||||
CPUARCH ARM
|
||||
ENDIAN LITTLE
|
||||
BITS 32
|
||||
REGION 0x00000000 0x00008000 RWX
|
||||
REGION 0x08000000 0x08100000 RWX
|
||||
REGION 0x10000000 0x18000000 RW
|
||||
REGION 0x18000000 0x18600000 RW
|
||||
REGION 0x1FF00000 0x1FF80000 RW
|
||||
REGION 0x1FF80000 0x20000000 RW
|
||||
REGION 0x20000000 0x28000000 RW
|
||||
|
||||
## .mmap - Compiled Memory Map
|
||||
### Header
|
||||
|
||||
The header is always little-endian
|
||||
|
||||
| Offset | Width | Meaning |
|
||||
|--------|-------|---------|
|
||||
| `0x00` | 4 | Magic number `MMAP` |
|
||||
| `0x04` | 4 | Version (Currently 0) |
|
||||
| `0x08` | 4 | Tag count |
|
||||
|
||||
### Tag format
|
||||
|
||||
| Offset | Width | Meaning |
|
||||
|--------|-------|---------|
|
||||
| `0x00` | 1 | Tag type |
|
||||
| `0x01` | 1 | Tag size |
|
||||
| `0x02` | 2 | Paddding |
|
||||
|
||||
### Supported tags
|
||||
| Tag Type | Size | Name |
|
||||
|-|-|-|
|
||||
| `0x00` | 1 | `DEVICETYPE` |
|
||||
| `0x01` | variable | `DEVICENAME` |
|
||||
| `0x02` | 1 | `CPUARCH` |
|
||||
| `0x03` | 1 | `ENDIAN` |
|
||||
| `0x04` | 1 | `BITS` |
|
||||
| `0x05` | `BITS`/4 + 1 | `REGION` |
|
||||
#### `DEVICETYPE`
|
||||
| Value | Meaning |
|
||||
|-|-|
|
||||
| `0` | `PC` |
|
||||
| `1` | `CONSOLE` |
|
||||
| `2` | `EMBEDDED` |
|
||||
|
||||
#### `CPUARCH`
|
||||
| Value | Meaning |
|
||||
|-|-|
|
||||
| 0 | `X86` |
|
||||
| 1 | `X86_64` |
|
||||
| 2 | `ARM` |
|
||||
|
||||
#### `ENDIAN`
|
||||
| Value | Meaning |
|
||||
|-|-|
|
||||
| 0 | `BIG` |
|
||||
| 1 | `LITTLE` |
|
||||
|
||||
#### `BITS`
|
||||
This is a 8-bit integer
|
||||
|
||||
#### `REGION`
|
||||
| Offset | Length | Meaning |
|
||||
|-|-|-|
|
||||
| 0 | `BITS`/8 | Start address |
|
||||
| `BITS`/8 | `BITS`/8 | End address |
|
||||
| `BITS`/4 | 1 | Permissions |
|
||||
|
||||
Permissions:
|
||||
| Value | Meaning |
|
||||
|-|-|
|
||||
| `0` | No permission |
|
||||
| `1` | `X` |
|
||||
| `2` | `W` |
|
||||
| `3` | `WX`|
|
||||
| `4` | `R` |
|
||||
| `5` | `RX` |
|
||||
| `6` | `RW` |
|
||||
| `7` | `RWX` |
|
|
@ -2,4 +2,6 @@ config["LOWEST_CPU"] = "arm11mpcore"
|
|||
config["ENABLE_HARD"] = get_yes_no("Enable VFP ABI", True)
|
||||
if not config["ENABLE_HARD"]:
|
||||
config["ENABLE_THUMB"] = get_yes_no("Enable Thumb")
|
||||
|
||||
import sys
|
||||
sys.argv=["","kernel/mmaps/3ds11.mc"]
|
||||
from buildtools import mmapcomp
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "../../../hw/3ds11/vectorinit/vectorinit.hpp"
|
||||
#include <base.hpp>
|
||||
#include <config.h>
|
||||
#include "../../../mmaps/3ds11.mh"
|
||||
|
||||
PICAfb term;
|
||||
void main();
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
config["LOWEST_CPU"] = "arm946e-s"
|
||||
config["ENABLE_THUMB"] = get_yes_no("Enable Thumb", True)
|
||||
|
||||
import sys
|
||||
sys.argv=["","kernel/mmaps/3ds9.mc"]
|
||||
from buildtools import mmapcomp
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "../../../hw/3ds9/vectorinit/vectorinit.hpp"
|
||||
#include <base.hpp>
|
||||
#include <config.h>
|
||||
#include "../../../mmaps/3ds9.mh"
|
||||
|
||||
PICAfb term;
|
||||
void main();
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
config["LOWEST_CPU"] = "cortex-a7"
|
||||
|
||||
import sys
|
||||
sys.argv=["","kernel/mmaps/raspi2.mc"]
|
||||
from buildtools import mmapcomp
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "../../../hw/raspi2/vector/vector.hpp"
|
||||
#include <base.hpp>
|
||||
#include <config.h>
|
||||
#include "../../../mmaps/raspi2.mh"
|
||||
|
||||
Serial term;
|
||||
void main();
|
||||
|
|
|
@ -8,6 +8,6 @@ if config["ENABLE_I2C"]:
|
|||
add_driver(True, "framebuffer")
|
||||
add_driver(False, "picafb")
|
||||
add_driver(False, "vectorinit")
|
||||
add_driver(False, "pmm")
|
||||
add_driver(True, "pmm")
|
||||
print("Enable complete Unicode font: NO (because of the size)")
|
||||
config["ENABLE_FRAMEBUFFER_UNICODE"] = False
|
||||
|
|
|
@ -2,6 +2,6 @@ config["ENABLE_EXTRA_MEMORY"] = get_yes_no("Enable 512KB of memory on n3DS", Tru
|
|||
add_driver(True, "framebuffer")
|
||||
add_driver(False, "picafb")
|
||||
add_driver(False, "vectorinit")
|
||||
add_driver(False, "pmm")
|
||||
add_driver(True, "pmm")
|
||||
print("Enable complete Unicode font: NO (because of the size)")
|
||||
config["ENABLE_FRAMEBUFFER_UNICODE"] = False
|
||||
|
|
134
kernel/hw/pmm/pmm.cpp
Normal file
134
kernel/hw/pmm/pmm.cpp
Normal file
|
@ -0,0 +1,134 @@
|
|||
#include "pmm.hpp"
|
||||
#include <base.hpp>
|
||||
enum class DEVICETYPE: uint8_t {
|
||||
PC,
|
||||
CONSOLE,
|
||||
EMBEDDED
|
||||
};
|
||||
enum class CPUARCH: uint8_t {
|
||||
X86,
|
||||
X86_64,
|
||||
ARM
|
||||
};
|
||||
enum class ENDIAN: uint8_t {
|
||||
BIG,
|
||||
LITTLE
|
||||
};
|
||||
enum class PERM: uint8_t {
|
||||
NONE,
|
||||
X,
|
||||
W,
|
||||
WX,
|
||||
R,
|
||||
RX,
|
||||
RW,
|
||||
RWX
|
||||
};
|
||||
struct MMAP {
|
||||
char magic[4];
|
||||
uint32_t version;
|
||||
uint32_t length;
|
||||
}__attribute__((packed));
|
||||
union MMAPTag {
|
||||
struct {
|
||||
uint8_t id;
|
||||
uint8_t size;
|
||||
}__attribute__((packed));
|
||||
struct {
|
||||
uint8_t id;
|
||||
uint8_t size;
|
||||
DEVICETYPE value;
|
||||
}__attribute__((packed)) DEVICETYPE;
|
||||
struct {
|
||||
uint8_t id;
|
||||
uint8_t size;
|
||||
char value[1];
|
||||
}__attribute__((packed)) DEVICENAME;
|
||||
struct {
|
||||
uint8_t id;
|
||||
uint8_t size;
|
||||
CPUARCH value;
|
||||
}__attribute__((packed)) CPUARCH;
|
||||
struct {
|
||||
uint8_t id;
|
||||
uint8_t size;
|
||||
ENDIAN endian;
|
||||
}__attribute__((packed)) ENDIAN;
|
||||
struct {
|
||||
uint8_t id;
|
||||
uint8_t size;
|
||||
uint8_t value;
|
||||
}__attribute__((packed)) BITS;
|
||||
struct {
|
||||
uint8_t id;
|
||||
uint8_t size;
|
||||
phys_t start;
|
||||
phys_t end;
|
||||
PERM permission;
|
||||
}__attribute__((packed)) REGION;
|
||||
};
|
||||
extern uint8_t mmap;
|
||||
|
||||
PMM_MMAP::PMM_MMAP(): PMM(0x1000) {
|
||||
MMAP &header = *((MMAP*)&mmap);
|
||||
if((header.magic[0] != 'M')||(header.magic[1] != 'M')||(header.magic[2] != 'A')||(header.magic[3] != 'P'))
|
||||
for(;;); //This is not a mmap
|
||||
#ifdef __BIG_ENDIAN__
|
||||
header.length = __builtin_bswap32(header.length);
|
||||
#endif
|
||||
uint8_t *off=(uint8_t*)(&header+1);
|
||||
for(uint32_t i=0;i<header.length;i++) {
|
||||
MMAPTag &tag = *((MMAPTag*)off);
|
||||
off+=tag.size;
|
||||
switch(tag.id) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 5:
|
||||
break; //Ignored for now
|
||||
case 2: //CPUARCH
|
||||
if(tag.CPUARCH.value !=
|
||||
#ifdef __i386__
|
||||
CPUARCH::X86
|
||||
#else
|
||||
#ifdef __x86_64__
|
||||
CPUARCH::X86_64
|
||||
#else
|
||||
CPUARCH::ARM
|
||||
#endif
|
||||
#endif
|
||||
)
|
||||
for(;;);
|
||||
break;
|
||||
case 3:
|
||||
hostEndian = tag.ENDIAN.endian ==
|
||||
#ifdef __BIG_ENDIAN__
|
||||
ENDIAN::BIG
|
||||
#else
|
||||
ENDIAN::LITTLE
|
||||
#endif
|
||||
;
|
||||
break;
|
||||
case 4:
|
||||
bits = tag.BITS.value;
|
||||
break;
|
||||
default:
|
||||
for(;;);
|
||||
}
|
||||
}
|
||||
}
|
||||
PMM_MMAP::~PMM_MMAP() {}
|
||||
auto PMM_MMAP::isFree(phys_t addr) -> bool {
|
||||
MMAP &header = *((MMAP*)&mmap);
|
||||
uint8_t *off=(uint8_t*)(&header+1);
|
||||
for(uint32_t i=0;i<header.length;i++) {
|
||||
MMAPTag &tag = *((MMAPTag*)off);
|
||||
off+=tag.size;
|
||||
if(tag.id != 5)
|
||||
continue;
|
||||
if((tag.REGION.start > addr) || (tag.REGION.end < addr))
|
||||
continue;
|
||||
if(tag.REGION.permission == PERM::RWX)
|
||||
return PMM::isFree(addr);
|
||||
}
|
||||
return false;
|
||||
}
|
11
kernel/hw/pmm/pmm.hpp
Normal file
11
kernel/hw/pmm/pmm.hpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
#include <pmm.hpp>
|
||||
class PMM_MMAP: public PMM {
|
||||
protected:
|
||||
uint8_t bits;
|
||||
bool hostEndian;
|
||||
virtual auto isFree(phys_t addr) -> bool;
|
||||
public:
|
||||
PMM_MMAP();
|
||||
virtual ~PMM_MMAP();
|
||||
};
|
|
@ -1,3 +1,4 @@
|
|||
add_driver(False, "uart")
|
||||
add_driver(False, "serial")
|
||||
add_driver(False, "vector")
|
||||
add_driver(True, "pmm")
|
||||
|
|
11
kernel/mmaps/3ds11.mc
Normal file
11
kernel/mmaps/3ds11.mc
Normal file
|
@ -0,0 +1,11 @@
|
|||
DEVICETYPE CONSOLE
|
||||
DEVICENAME 3DS11
|
||||
CPUARCH ARM
|
||||
ENDIAN LITTLE
|
||||
BITS 32
|
||||
REGION 0x00000000 0x00010000 RX
|
||||
REGION 0x10000000 0x18000000 RW
|
||||
REGION 0x18000000 0x18600000 RW
|
||||
REGION 0x1FF00000 0x1FF80000 RW
|
||||
REGION 0x1FF80000 0x20000000 RW
|
||||
REGION 0x20000000 0x28000000 RWX
|
14
kernel/mmaps/3ds9.mc
Normal file
14
kernel/mmaps/3ds9.mc
Normal file
|
@ -0,0 +1,14 @@
|
|||
DEVICETYPE CONSOLE
|
||||
DEVICENAME 3DS9
|
||||
CPUARCH ARM
|
||||
ENDIAN LITTLE
|
||||
BITS 32
|
||||
REGION 0x00000000 0x00008000 RW
|
||||
REGION 0x08000000 0x08100000 RWX
|
||||
REGION 0x10000000 0x18000000 RW
|
||||
REGION 0x18000000 0x18600000 RW
|
||||
REGION 0x1FF00000 0x1FF80000 RW
|
||||
REGION 0x1FF80000 0x20000000 RW
|
||||
REGION 0x20000000 0x28000000 RW
|
||||
REGION 0xFFF00000 0xFFF04000 RW
|
||||
REGION 0xFFFF0000 0x00000000 RX
|
6
kernel/mmaps/raspi2.mc
Normal file
6
kernel/mmaps/raspi2.mc
Normal file
|
@ -0,0 +1,6 @@
|
|||
DEVICETYPE CONSOLE
|
||||
DEVICENAME RASPI2
|
||||
CPUARCH ARM
|
||||
ENDIAN LITTLE
|
||||
BITS 32
|
||||
REGION 0x00000000 0x40000000 RWX
|
|
@ -11,3 +11,11 @@ void setMainTTY(TTY *obj);
|
|||
* Halts the kernel due to a unresolvable error
|
||||
*/
|
||||
extern "C" void panic(const char* s);
|
||||
|
||||
#if !defined(__LITTLE_ENDIAN__) || !defined(__BIG_ENDIAN__)
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define __LITTLE_ENDIAN__
|
||||
#else
|
||||
#define __BIG_ENDIAN__
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
typedef uintptr_t phys_t; ///< Type used for physical addresses
|
||||
/**
|
||||
* A single entry in the PMM list
|
||||
|
@ -7,13 +9,6 @@ struct PMM_ent {
|
|||
PMM_ent* next; ///< Next element in the list
|
||||
phys_t val; ///< This for not having to cast in the code.
|
||||
};
|
||||
/**
|
||||
* Structure for a memory map
|
||||
*/
|
||||
struct mmap_ent {
|
||||
phys_t start;
|
||||
phys_t end;
|
||||
}
|
||||
/**
|
||||
* Physical memory manager. It stores the free memory in a linked list
|
||||
*/
|
||||
|
@ -23,12 +18,12 @@ class PMM {
|
|||
virtual auto isFree(phys_t addr) -> bool; ///< Returns true if the provided page is free to use
|
||||
phys_t page_size; ///< Contains the size of a single memory page, in bytes
|
||||
public:
|
||||
PMM(phys_t page_size, mmap_ent *entries, int length);
|
||||
PMM(phys_t page_size);
|
||||
virtual ~PMM();
|
||||
virtual auto operator<<(phys_t page) -> PMM &; ///< Frees a page. O(1)
|
||||
virtual auto operator>>(phys_t &page) -> PMM &; ///< Allocates a page. O(1)
|
||||
virtual auto operator,(size_t no_pages) -> phys_t; ///< Allocates multiple pages. O(n²)
|
||||
virtual auto operator(phys_t pages,size_t no_pages) -> void; ///< Deallocates multiple pages. O(n)
|
||||
virtual auto operator()(phys_t pages,size_t no_pages) -> void; ///< Deallocates multiple pages. O(n)
|
||||
virtual auto operator&&(phys_t page) -> bool; //Returns true if this page is free. O(n).
|
||||
};
|
||||
/**
|
||||
|
@ -37,4 +32,3 @@ class PMM {
|
|||
#define in and
|
||||
|
||||
auto operator&&(phys_t a, PMM mm) -> bool; ///< Returns true when page is free. Used for syntax `page in pmm`
|
||||
auto operator&&(phys_t a, PMM *mm) -> bool; ///< Returns true when page is free. Present in case that mm is a pointer.
|
||||
|
|
|
@ -11,22 +11,16 @@ auto PMM::isFree(phys_t addr) -> bool {
|
|||
return false;
|
||||
return true;
|
||||
}
|
||||
PMM::PMM(phys_t page_size, mmap_ent *entries, int length): page_size(page_size), head(nullptr) {
|
||||
for(int i=0;i< length; i++) {
|
||||
for(phys_t j=entries[i].start;j<entries[i].end;j+=page_size) {
|
||||
if(isFree(j))
|
||||
*this << j;
|
||||
}
|
||||
}
|
||||
PMM::PMM(phys_t page_size): page_size(page_size), head(nullptr) {
|
||||
}
|
||||
PMM::~PMM() {}
|
||||
|
||||
auto PMM::operator<<(phys_t page) -> PMM & {
|
||||
*this(page,1);
|
||||
(*this)(page,1);
|
||||
return *this;
|
||||
}
|
||||
auto PMM::operator>>(phys_t &page) -> PMM & {
|
||||
page = *this, 1;
|
||||
page = (*this, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -62,7 +56,7 @@ auto PMM::operator,(size_t no_pages) -> phys_t {
|
|||
}
|
||||
panic("Not enough continuous free memory is available.");
|
||||
}
|
||||
auto PMM::operator(phys_t pages, size_t no_pages) -> void {
|
||||
auto PMM::operator()(phys_t pages, size_t no_pages) -> void {
|
||||
for(size_t i=0; i<no_pages; i++, pages+=page_size) {
|
||||
PMM_ent *curr=(PMM_ent *)pages;
|
||||
curr->next=head;
|
||||
|
@ -70,10 +64,10 @@ auto PMM::operator(phys_t pages, size_t no_pages) -> void {
|
|||
head=curr;
|
||||
}
|
||||
}
|
||||
virtual auto operator&&(phys_t page) -> bool {
|
||||
auto PMM::operator&&(phys_t page) -> bool {
|
||||
PMM_ent *curr = head;
|
||||
while(curr) {
|
||||
if(curr->value==page)
|
||||
if(curr->val==page)
|
||||
return true;
|
||||
curr=curr->next;
|
||||
}
|
||||
|
@ -82,6 +76,3 @@ virtual auto operator&&(phys_t page) -> bool {
|
|||
auto operator&&(phys_t a, PMM mm) -> bool {
|
||||
return mm && a;
|
||||
}
|
||||
auto operator&&(phys_t a, PMM *mm) -> bool {
|
||||
return a in *mm;
|
||||
}
|
Loading…
Reference in a new issue