mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-29 16:21:29 +00:00
Add Regions concept to Task.
This commit is contained in:
parent
5b10846bed
commit
3649638259
Notes:
sideshowbarker
2024-07-19 18:46:23 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/36496382597
|
@ -68,9 +68,9 @@ auto MemoryManager::ensurePTE(LinearAddress linearAddress) -> PageTableEntry
|
||||||
pde.setWritable(true);
|
pde.setWritable(true);
|
||||||
} else if (pageDirectoryIndex == 1) {
|
} else if (pageDirectoryIndex == 1) {
|
||||||
pde.setPageTableBase((dword)m_pageTableOne);
|
pde.setPageTableBase((dword)m_pageTableOne);
|
||||||
pde.setUserAllowed(false);
|
pde.setUserAllowed(true);
|
||||||
pde.setPresent(true);
|
pde.setPresent(true);
|
||||||
pde.setWritable(false);
|
pde.setWritable(true);
|
||||||
} else {
|
} else {
|
||||||
// FIXME: We need an allocator!
|
// FIXME: We need an allocator!
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
@ -120,7 +120,6 @@ RetainPtr<Zone> MemoryManager::createZone(size_t size)
|
||||||
|
|
||||||
Vector<PhysicalAddress> MemoryManager::allocatePhysicalPages(size_t count)
|
Vector<PhysicalAddress> MemoryManager::allocatePhysicalPages(size_t count)
|
||||||
{
|
{
|
||||||
kprintf("MM: alloc %u pages from %u available\n", count, m_freePages.size());
|
|
||||||
if (count > m_freePages.size())
|
if (count > m_freePages.size())
|
||||||
return { };
|
return { };
|
||||||
|
|
||||||
|
@ -128,7 +127,6 @@ Vector<PhysicalAddress> MemoryManager::allocatePhysicalPages(size_t count)
|
||||||
pages.ensureCapacity(count);
|
pages.ensureCapacity(count);
|
||||||
for (size_t i = 0; i < count; ++i)
|
for (size_t i = 0; i < count; ++i)
|
||||||
pages.append(m_freePages.takeLast());
|
pages.append(m_freePages.takeLast());
|
||||||
kprintf("MM: returning the pages (%u of them)\n", pages.size());
|
|
||||||
return pages;
|
return pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,19 +140,24 @@ byte* MemoryManager::quickMapOnePage(PhysicalAddress physicalAddress)
|
||||||
return (byte*)(4 * MB);
|
return (byte*)(4 * MB);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryManager::unmapZonesForTask(Task& task)
|
bool MemoryManager::unmapRegionsForTask(Task& task)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryManager::mapZonesForTask(Task& task)
|
bool MemoryManager::mapRegionsForTask(Task& task)
|
||||||
{
|
{
|
||||||
for (auto& mappedZone : task.m_mappedZones) {
|
for (auto& region : task.m_regions) {
|
||||||
auto& zone = *mappedZone.zone;
|
auto& zone = *region->zone;
|
||||||
for (size_t i = 0; i < zone.m_pages.size(); ++i) {
|
for (size_t i = 0; i < zone.m_pages.size(); ++i) {
|
||||||
auto pte = ensurePTE(mappedZone.linearAddress.offset(i * PAGE_SIZE));
|
auto laddr = region->linearAddress.offset(i * PAGE_SIZE);
|
||||||
|
auto pte = ensurePTE(laddr);
|
||||||
pte.setPhysicalPageBase(zone.m_pages[i].get());
|
pte.setPhysicalPageBase(zone.m_pages[i].get());
|
||||||
pte.setPresent(true);
|
pte.setPresent(true);
|
||||||
|
pte.setWritable(true);
|
||||||
|
pte.setUserAllowed(!task.isRing0());
|
||||||
|
|
||||||
|
kprintf("MM: >> Mapped L%x => P%x <<\n", laddr, zone.m_pages[i].get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -49,8 +49,8 @@ public:
|
||||||
// HACK: don't use this jeez :(
|
// HACK: don't use this jeez :(
|
||||||
byte* quickMapOnePage(PhysicalAddress);
|
byte* quickMapOnePage(PhysicalAddress);
|
||||||
|
|
||||||
bool mapZonesForTask(Task&);
|
bool mapRegionsForTask(Task&);
|
||||||
bool unmapZonesForTask(Task&);
|
bool unmapRegionsForTask(Task&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MemoryManager();
|
MemoryManager();
|
||||||
|
|
|
@ -74,7 +74,7 @@ void Task::allocateLDT()
|
||||||
static const WORD numLDTEntries = 4;
|
static const WORD numLDTEntries = 4;
|
||||||
WORD newLDTSelector = allocateGDTEntry();
|
WORD newLDTSelector = allocateGDTEntry();
|
||||||
m_ldtEntries = new Descriptor[numLDTEntries];
|
m_ldtEntries = new Descriptor[numLDTEntries];
|
||||||
#if 1
|
#if 0
|
||||||
kprintf("new ldt selector = %x\n", newLDTSelector);
|
kprintf("new ldt selector = %x\n", newLDTSelector);
|
||||||
kprintf("new ldt table at = %p\n", m_ldtEntries);
|
kprintf("new ldt table at = %p\n", m_ldtEntries);
|
||||||
kprintf("new ldt table size = %u\n", (numLDTEntries * 8) - 1);
|
kprintf("new ldt table size = %u\n", (numLDTEntries * 8) - 1);
|
||||||
|
@ -92,12 +92,15 @@ void Task::allocateLDT()
|
||||||
m_tss.ldt = newLDTSelector;
|
m_tss.ldt = newLDTSelector;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Task::mapZone(LinearAddress address, RetainPtr<Zone>&& zone)
|
Task::Region* Task::allocateRegion(size_t size, String&& name)
|
||||||
{
|
{
|
||||||
// FIXME: This needs sanity checks. What if this overlaps existing zones?
|
// FIXME: This needs sanity checks. What if this overlaps existing regions?
|
||||||
kprintf("mapped zone with size %u at %x\n", zone->size(), address.get());
|
|
||||||
m_mappedZones.append({ address, move(zone) });
|
auto zone = MemoryManager::the().createZone(PAGE_SIZE);
|
||||||
return true;
|
ASSERT(zone);
|
||||||
|
m_regions.append(make<Region>(m_nextRegion, size, move(zone), move(name)));
|
||||||
|
m_nextRegion = m_nextRegion.offset(size).offset(16384);
|
||||||
|
return m_regions.last().ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring)
|
Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring)
|
||||||
|
@ -108,16 +111,13 @@ Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring)
|
||||||
, m_state(Runnable)
|
, m_state(Runnable)
|
||||||
, m_ring(ring)
|
, m_ring(ring)
|
||||||
{
|
{
|
||||||
|
m_nextRegion = LinearAddress(0x600000);
|
||||||
|
|
||||||
|
Region* codeRegion = nullptr;
|
||||||
if (!isRing0()) {
|
if (!isRing0()) {
|
||||||
auto zone = MemoryManager::the().createZone(PAGE_SIZE);
|
codeRegion = allocateRegion(4096, "code");
|
||||||
ASSERT(zone);
|
ASSERT(codeRegion);
|
||||||
|
bool success = copyToZone(*codeRegion->zone, (void*)e, PAGE_SIZE);
|
||||||
kprintf("New task zone: { size: %u }\n", zone->size());
|
|
||||||
|
|
||||||
bool success = mapZone(LinearAddress(0x300000), zone.copyRef());
|
|
||||||
ASSERT(success);
|
|
||||||
|
|
||||||
success = copyToZone(*zone, (void*)e, PAGE_SIZE);
|
|
||||||
ASSERT(success);
|
ASSERT(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,22 +157,31 @@ Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring)
|
||||||
if (isRing0()) {
|
if (isRing0()) {
|
||||||
m_tss.eip = (DWORD)m_entry;
|
m_tss.eip = (DWORD)m_entry;
|
||||||
} else {
|
} else {
|
||||||
m_tss.eip = m_mappedZones[0].linearAddress.get();
|
m_tss.eip = codeRegion->linearAddress.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("basically ready\n");
|
kprintf("basically ready\n");
|
||||||
|
|
||||||
// NOTE: Each task gets 4KB of stack.
|
// NOTE: Each task gets 4KB of stack.
|
||||||
// This memory is leaked ATM.
|
|
||||||
// But uh, there's also no process termination, so I guess it's not technically leaked...
|
|
||||||
static const DWORD defaultStackSize = 4096;
|
static const DWORD defaultStackSize = 4096;
|
||||||
m_stackTop = ((DWORD)kmalloc(defaultStackSize) + defaultStackSize) & 0xffffff8;
|
|
||||||
m_tss.esp = m_stackTop;
|
if (isRing0()) {
|
||||||
|
// FIXME: This memory is leaked.
|
||||||
|
// But uh, there's also no kernel task termination, so I guess it's not technically leaked...
|
||||||
|
m_stackTop = ((DWORD)kmalloc(defaultStackSize) + defaultStackSize) & 0xffffff8;
|
||||||
|
m_tss.esp = m_stackTop;
|
||||||
|
} else {
|
||||||
|
auto* region = allocateRegion(defaultStackSize, "stack");
|
||||||
|
ASSERT(region);
|
||||||
|
m_stackTop = region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8;
|
||||||
|
m_tss.esp = m_stackTop;
|
||||||
|
}
|
||||||
|
|
||||||
if (ring == Ring3) {
|
if (ring == Ring3) {
|
||||||
// Set up a separate stack for Ring0.
|
// Set up a separate stack for Ring0.
|
||||||
// FIXME: Don't leak this stack either.
|
// FIXME: Don't leak this stack either.
|
||||||
DWORD ring0StackTop = ((DWORD)kmalloc(defaultStackSize) + defaultStackSize) & 0xffffff8;
|
m_kernelStack = kmalloc(defaultStackSize);
|
||||||
|
DWORD ring0StackTop = ((DWORD)m_kernelStack + defaultStackSize) & 0xffffff8;
|
||||||
m_tss.ss0 = 0x10;
|
m_tss.ss0 = 0x10;
|
||||||
m_tss.esp0 = ring0StackTop;
|
m_tss.esp0 = ring0StackTop;
|
||||||
}
|
}
|
||||||
|
@ -200,11 +209,36 @@ Task::~Task()
|
||||||
system.nprocess--;
|
system.nprocess--;
|
||||||
delete [] m_ldtEntries;
|
delete [] m_ldtEntries;
|
||||||
m_ldtEntries = nullptr;
|
m_ldtEntries = nullptr;
|
||||||
|
|
||||||
|
// FIXME: The task's kernel stack is currently leaked, because otherwise we GPF.
|
||||||
|
// This obviously needs figuring out.
|
||||||
|
#if 0
|
||||||
|
if (m_kernelStack) {
|
||||||
|
kfree(m_kernelStack);
|
||||||
|
m_kernelStack = nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Task::dumpRegions()
|
||||||
|
{
|
||||||
|
kprintf("Task %s(%u) regions:\n", name().characters(), pid());
|
||||||
|
kprintf("BEGIN END SIZE NAME\n");
|
||||||
|
for (auto& region : m_regions) {
|
||||||
|
kprintf("%x -- %x %x %s\n",
|
||||||
|
region->linearAddress.get(),
|
||||||
|
region->linearAddress.offset(region->size - 1).get(),
|
||||||
|
region->size,
|
||||||
|
region->name.characters());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::taskDidCrash(Task* crashedTask)
|
void Task::taskDidCrash(Task* crashedTask)
|
||||||
{
|
{
|
||||||
crashedTask->setState(Crashing);
|
crashedTask->setState(Crashing);
|
||||||
|
|
||||||
|
crashedTask->dumpRegions();
|
||||||
|
|
||||||
s_tasks->remove(crashedTask);
|
s_tasks->remove(crashedTask);
|
||||||
|
|
||||||
if (!scheduleNewTask()) {
|
if (!scheduleNewTask()) {
|
||||||
|
@ -327,9 +361,9 @@ static bool contextSwitch(Task* t)
|
||||||
if (current->state() == Task::Running)
|
if (current->state() == Task::Running)
|
||||||
current->setState(Task::Runnable);
|
current->setState(Task::Runnable);
|
||||||
|
|
||||||
bool success = MemoryManager::the().unmapZonesForTask(*current);
|
bool success = MemoryManager::the().unmapRegionsForTask(*current);
|
||||||
ASSERT(success);
|
ASSERT(success);
|
||||||
success = MemoryManager::the().mapZonesForTask(*t);
|
success = MemoryManager::the().mapRegionsForTask(*t);
|
||||||
ASSERT(success);
|
ASSERT(success);
|
||||||
|
|
||||||
current = t;
|
current = t;
|
||||||
|
@ -523,3 +557,15 @@ void Task::setError(int error)
|
||||||
{
|
{
|
||||||
m_error = error;
|
m_error = error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Task::Region::Region(LinearAddress a, size_t s, RetainPtr<Zone>&& z, String&& n)
|
||||||
|
: linearAddress(a)
|
||||||
|
, size(s)
|
||||||
|
, zone(move(z))
|
||||||
|
, name(move(n))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Task::Region::~Region()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -97,10 +97,11 @@ public:
|
||||||
|
|
||||||
static void taskDidCrash(Task*);
|
static void taskDidCrash(Task*);
|
||||||
|
|
||||||
|
void dumpRegions();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class MemoryManager;
|
friend class MemoryManager;
|
||||||
|
|
||||||
bool mapZone(LinearAddress, RetainPtr<Zone>&&);
|
|
||||||
FileHandle* openFile(String&&);
|
FileHandle* openFile(String&&);
|
||||||
|
|
||||||
void allocateLDT();
|
void allocateLDT();
|
||||||
|
@ -124,13 +125,22 @@ private:
|
||||||
Vector<OwnPtr<FileHandle>> m_fileHandles;
|
Vector<OwnPtr<FileHandle>> m_fileHandles;
|
||||||
RingLevel m_ring { Ring0 };
|
RingLevel m_ring { Ring0 };
|
||||||
int m_error { 0 };
|
int m_error { 0 };
|
||||||
|
void* m_kernelStack { nullptr };
|
||||||
|
|
||||||
struct MappedZone {
|
struct Region {
|
||||||
|
Region(LinearAddress, size_t, RetainPtr<Zone>&&, String&&);
|
||||||
|
~Region();
|
||||||
LinearAddress linearAddress;
|
LinearAddress linearAddress;
|
||||||
|
size_t size { 0 };
|
||||||
RetainPtr<Zone> zone;
|
RetainPtr<Zone> zone;
|
||||||
|
String name;
|
||||||
};
|
};
|
||||||
|
Region* allocateRegion(size_t, String&& name);
|
||||||
|
|
||||||
Vector<MappedZone> m_mappedZones;
|
Vector<OwnPtr<Region>> m_regions;
|
||||||
|
|
||||||
|
// FIXME: Implement some kind of ASLR?
|
||||||
|
LinearAddress m_nextRegion;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void task_init();
|
extern void task_init();
|
||||||
|
|
|
@ -73,12 +73,22 @@ EH_ENTRY(13);
|
||||||
void exception_13_handler()
|
void exception_13_handler()
|
||||||
{
|
{
|
||||||
auto& regs = *reinterpret_cast<RegisterDump*>(exception_state_dump);
|
auto& regs = *reinterpret_cast<RegisterDump*>(exception_state_dump);
|
||||||
kprintf("Process crash: %u(%s)\n", current->pid(), current->name().characters());
|
kprintf("%s crash: %u(%s)\n", current->isRing0() ? "Kernel" : "Process", current->pid(), current->name().characters());
|
||||||
|
|
||||||
|
word ss;
|
||||||
|
dword esp;
|
||||||
|
if (current->isRing0()) {
|
||||||
|
ss = regs.ds;
|
||||||
|
esp = regs.esp;
|
||||||
|
} else {
|
||||||
|
ss = regs.ss_if_crossRing;
|
||||||
|
esp = regs.esp_if_crossRing;
|
||||||
|
}
|
||||||
|
|
||||||
kprintf("exception code: %w\n", exception_code);
|
kprintf("exception code: %w\n", exception_code);
|
||||||
kprintf("pc=%w:%x ds=%w es=%w fs=%w gs=%w\n", regs.cs, regs.eip, regs.ds, regs.es, regs.fs, regs.gs);
|
kprintf("pc=%w:%x ds=%w es=%w fs=%w gs=%w\n", regs.cs, regs.eip, regs.ds, regs.es, regs.fs, regs.gs);
|
||||||
kprintf("eax=%x ebx=%x ecx=%x edx=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx);
|
kprintf("eax=%x ebx=%x ecx=%x edx=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx);
|
||||||
kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, regs.esp, regs.esi, regs.edi);
|
kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, esp, regs.esi, regs.edi);
|
||||||
|
|
||||||
if (current->isRing0()) {
|
if (current->isRing0()) {
|
||||||
kprintf("Oh shit, we've crashed in ring 0 :(\n");
|
kprintf("Oh shit, we've crashed in ring 0 :(\n");
|
||||||
|
@ -104,10 +114,20 @@ void exception_14_handler()
|
||||||
exception_code & 2 ? "write" : "read",
|
exception_code & 2 ? "write" : "read",
|
||||||
faultAddress);
|
faultAddress);
|
||||||
|
|
||||||
|
word ss;
|
||||||
|
dword esp;
|
||||||
|
if (current->isRing0()) {
|
||||||
|
ss = regs.ds;
|
||||||
|
esp = regs.esp;
|
||||||
|
} else {
|
||||||
|
ss = regs.ss_if_crossRing;
|
||||||
|
esp = regs.esp_if_crossRing;
|
||||||
|
}
|
||||||
|
|
||||||
kprintf("exception code: %w\n", exception_code);
|
kprintf("exception code: %w\n", exception_code);
|
||||||
kprintf("pc=%w:%x ds=%w es=%w fs=%w gs=%w\n", regs.cs, regs.eip, regs.ds, regs.es, regs.fs, regs.gs);
|
kprintf("pc=%w:%x ds=%w es=%w fs=%w gs=%w\n", regs.cs, regs.eip, regs.ds, regs.es, regs.fs, regs.gs);
|
||||||
kprintf("eax=%x ebx=%x ecx=%x edx=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx);
|
kprintf("eax=%x ebx=%x ecx=%x edx=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx);
|
||||||
kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, regs.esp, regs.esi, regs.edi);
|
kprintf("ebp=%x esp=%x esi=%x edi=%x\n", regs.ebp, esp, regs.esi, regs.edi);
|
||||||
|
|
||||||
if (current->isRing0())
|
if (current->isRing0())
|
||||||
HANG;
|
HANG;
|
||||||
|
|
|
@ -131,6 +131,8 @@ struct RegisterDump {
|
||||||
WORD cs;
|
WORD cs;
|
||||||
WORD __csPadding;
|
WORD __csPadding;
|
||||||
DWORD eflags;
|
DWORD eflags;
|
||||||
|
DWORD esp_if_crossRing;
|
||||||
|
WORD ss_if_crossRing;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
inline constexpr dword pageBaseOf(dword address)
|
inline constexpr dword pageBaseOf(dword address)
|
||||||
|
|
|
@ -76,6 +76,14 @@ static void user_main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void user_kprintf_main() NORETURN;
|
||||||
|
static void user_kprintf_main()
|
||||||
|
{
|
||||||
|
DO_SYSCALL_A1(0x4000, 0);
|
||||||
|
kprintf("This should not work!\n");
|
||||||
|
HANG;
|
||||||
|
}
|
||||||
|
|
||||||
system_t system;
|
system_t system;
|
||||||
|
|
||||||
void banner()
|
void banner()
|
||||||
|
@ -155,10 +163,11 @@ void init()
|
||||||
|
|
||||||
//new Task(motd_main, "motd", IPC::Handle::MotdTask, Task::Ring0);
|
//new Task(motd_main, "motd", IPC::Handle::MotdTask, Task::Ring0);
|
||||||
new Task(user_main, "user", IPC::Handle::UserTask, Task::Ring3);
|
new Task(user_main, "user", IPC::Handle::UserTask, Task::Ring3);
|
||||||
|
new Task(user_kprintf_main, "user_kprintf", IPC::Handle::UserTask, Task::Ring3);
|
||||||
|
|
||||||
//vfs->listDirectory("/");
|
//vfs->listDirectory("/");
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
{
|
{
|
||||||
auto motdFile = vfs->open("/motd.txt");
|
auto motdFile = vfs->open("/motd.txt");
|
||||||
ASSERT(motdFile);
|
ASSERT(motdFile);
|
||||||
|
|
Loading…
Reference in a new issue