diff --git a/src/include/syscalls.h b/src/include/syscalls.h index e52e178..2a35dd8 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -11,53 +11,20 @@ SYS_IO_IN = 3, SYS_IO_OUT = 4, SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_PROVIDER = 7, } SyscallIds; typedef struct Syscall { uint32_t function; - void *address; + uint32_t parameters[4]; + uint32_t returnValue; void *esp; void *cr3; struct Syscall *respondingTo; void *service; bool resume; bool avoidReschedule; - struct Syscall *writeBack; } Syscall; -typedef struct { - Syscall; - void *handler; - char *name; -} RegisterServiceProviderSyscall; - -typedef struct { - Syscall; - char *serviceName; - char *providerName; - uint32_t dataSize; - void *data; -} RequestSyscall; - -typedef struct { - Syscall; - uint16_t port; - uint8_t size; -} IOPortSyscall; - -typedef struct { - IOPortSyscall; - uint32_t result; -} IOPortInSyscall; - -typedef struct { - IOPortSyscall; - uint32_t value; -} IOPortOutSyscall; - -typedef struct { - Syscall; - char *programName; -} LoadFromInitrdSyscall; - #endif diff --git a/src/include/syscalls.h b/src/include/syscalls.h index e52e178..2a35dd8 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -11,53 +11,20 @@ SYS_IO_IN = 3, SYS_IO_OUT = 4, SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_PROVIDER = 7, } SyscallIds; typedef struct Syscall { uint32_t function; - void *address; + uint32_t parameters[4]; + uint32_t returnValue; void *esp; void *cr3; struct Syscall *respondingTo; void *service; bool resume; bool avoidReschedule; - struct Syscall *writeBack; } Syscall; -typedef struct { - Syscall; - void *handler; - char *name; -} RegisterServiceProviderSyscall; - -typedef struct { - Syscall; - char *serviceName; - char *providerName; - uint32_t dataSize; - void *data; -} RequestSyscall; - -typedef struct { - Syscall; - uint16_t port; - uint8_t size; -} IOPortSyscall; - -typedef struct { - IOPortSyscall; - uint32_t result; -} IOPortInSyscall; - -typedef struct { - IOPortSyscall; - uint32_t value; -} IOPortOutSyscall; - -typedef struct { - Syscall; - char *programName; -} LoadFromInitrdSyscall; - #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 49ac65c..a70cf75 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -22,20 +22,17 @@ Provider *provider = findProvider(service, "main"); Syscall *runTask = malloc(sizeof(Syscall)); runTask->function = SYS_RUN; - runTask->address = provider->address; runTask->resume = true; runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); runTask->esp = malloc(0x1000); runTask->respondingTo = respondingTo; runTask->service = service; memset(runTask->esp, 0, 0x1000); - runTask->esp += 0xFFC; - *(void **)runTask->esp = &runEnd; + runTask->esp += 0xFF8; + *(void **)runTask->esp = provider->address; + *(void **)(runTask->esp + 4) = &runEnd; sharePage(&service->pagingInfo, runTask->esp, runTask->esp); listAdd(&callsToProcess, runTask); - if (!runTask->address) { - asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); - } return runTask; } @@ -68,8 +65,6 @@ call->resume = true; if (!call->avoidReschedule) { listAdd(&callsToProcess, call); - void *temporary = mapTemporary(call->writeBack); - memcpy(call, temporary, sizeof(IOPortInSyscall)); } } } diff --git a/src/include/syscalls.h b/src/include/syscalls.h index e52e178..2a35dd8 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -11,53 +11,20 @@ SYS_IO_IN = 3, SYS_IO_OUT = 4, SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_PROVIDER = 7, } SyscallIds; typedef struct Syscall { uint32_t function; - void *address; + uint32_t parameters[4]; + uint32_t returnValue; void *esp; void *cr3; struct Syscall *respondingTo; void *service; bool resume; bool avoidReschedule; - struct Syscall *writeBack; } Syscall; -typedef struct { - Syscall; - void *handler; - char *name; -} RegisterServiceProviderSyscall; - -typedef struct { - Syscall; - char *serviceName; - char *providerName; - uint32_t dataSize; - void *data; -} RequestSyscall; - -typedef struct { - Syscall; - uint16_t port; - uint8_t size; -} IOPortSyscall; - -typedef struct { - IOPortSyscall; - uint32_t result; -} IOPortInSyscall; - -typedef struct { - IOPortSyscall; - uint32_t value; -} IOPortOutSyscall; - -typedef struct { - Syscall; - char *programName; -} LoadFromInitrdSyscall; - #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 49ac65c..a70cf75 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -22,20 +22,17 @@ Provider *provider = findProvider(service, "main"); Syscall *runTask = malloc(sizeof(Syscall)); runTask->function = SYS_RUN; - runTask->address = provider->address; runTask->resume = true; runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); runTask->esp = malloc(0x1000); runTask->respondingTo = respondingTo; runTask->service = service; memset(runTask->esp, 0, 0x1000); - runTask->esp += 0xFFC; - *(void **)runTask->esp = &runEnd; + runTask->esp += 0xFF8; + *(void **)runTask->esp = provider->address; + *(void **)(runTask->esp + 4) = &runEnd; sharePage(&service->pagingInfo, runTask->esp, runTask->esp); listAdd(&callsToProcess, runTask); - if (!runTask->address) { - asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); - } return runTask; } @@ -68,8 +65,6 @@ call->resume = true; if (!call->avoidReschedule) { listAdd(&callsToProcess, call); - void *temporary = mapTemporary(call->writeBack); - memcpy(call, temporary, sizeof(IOPortInSyscall)); } } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index e715905..c6aa5f9 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -15,7 +15,9 @@ block->allocatedCoarse &= ~(1 << coarse); break; } - return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + void *result = ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + memset(result, 0, block->blockSize); + return result; } void *malloc(uint32_t size) { diff --git a/src/include/syscalls.h b/src/include/syscalls.h index e52e178..2a35dd8 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -11,53 +11,20 @@ SYS_IO_IN = 3, SYS_IO_OUT = 4, SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_PROVIDER = 7, } SyscallIds; typedef struct Syscall { uint32_t function; - void *address; + uint32_t parameters[4]; + uint32_t returnValue; void *esp; void *cr3; struct Syscall *respondingTo; void *service; bool resume; bool avoidReschedule; - struct Syscall *writeBack; } Syscall; -typedef struct { - Syscall; - void *handler; - char *name; -} RegisterServiceProviderSyscall; - -typedef struct { - Syscall; - char *serviceName; - char *providerName; - uint32_t dataSize; - void *data; -} RequestSyscall; - -typedef struct { - Syscall; - uint16_t port; - uint8_t size; -} IOPortSyscall; - -typedef struct { - IOPortSyscall; - uint32_t result; -} IOPortInSyscall; - -typedef struct { - IOPortSyscall; - uint32_t value; -} IOPortOutSyscall; - -typedef struct { - Syscall; - char *programName; -} LoadFromInitrdSyscall; - #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 49ac65c..a70cf75 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -22,20 +22,17 @@ Provider *provider = findProvider(service, "main"); Syscall *runTask = malloc(sizeof(Syscall)); runTask->function = SYS_RUN; - runTask->address = provider->address; runTask->resume = true; runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); runTask->esp = malloc(0x1000); runTask->respondingTo = respondingTo; runTask->service = service; memset(runTask->esp, 0, 0x1000); - runTask->esp += 0xFFC; - *(void **)runTask->esp = &runEnd; + runTask->esp += 0xFF8; + *(void **)runTask->esp = provider->address; + *(void **)(runTask->esp + 4) = &runEnd; sharePage(&service->pagingInfo, runTask->esp, runTask->esp); listAdd(&callsToProcess, runTask); - if (!runTask->address) { - asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); - } return runTask; } @@ -68,8 +65,6 @@ call->resume = true; if (!call->avoidReschedule) { listAdd(&callsToProcess, call); - void *temporary = mapTemporary(call->writeBack); - memcpy(call, temporary, sizeof(IOPortInSyscall)); } } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index e715905..c6aa5f9 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -15,7 +15,9 @@ block->allocatedCoarse &= ~(1 << coarse); break; } - return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + void *result = ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + memset(result, 0, block->blockSize); + return result; } void *malloc(uint32_t size) { diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index f538328..9c47365 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -2,7 +2,7 @@ global runFunction global runEnd -global runEndSyscall +global temporaryESP extern currentSyscall @@ -13,17 +13,17 @@ mov eax, esp mov [temporaryESP], eax mov ebx, [currentSyscall] - mov ecx, [ebx + 8] + mov ecx, [ebx + 24] mov ebp, ecx - mov edx, [ebx + 4] - mov eax, [ebx + 12] + mov edx, returnPoint + mov eax, [ebx + 28] + mov ebx, [ebx + 20] mov cr3, eax + mov eax, ebx sysexit runEnd: mov eax, 0 sysenter -runEndSyscall: - mov eax, [temporaryESP] - mov esp, eax - pop ebp + +returnPoint: ret diff --git a/src/include/syscalls.h b/src/include/syscalls.h index e52e178..2a35dd8 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -11,53 +11,20 @@ SYS_IO_IN = 3, SYS_IO_OUT = 4, SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_PROVIDER = 7, } SyscallIds; typedef struct Syscall { uint32_t function; - void *address; + uint32_t parameters[4]; + uint32_t returnValue; void *esp; void *cr3; struct Syscall *respondingTo; void *service; bool resume; bool avoidReschedule; - struct Syscall *writeBack; } Syscall; -typedef struct { - Syscall; - void *handler; - char *name; -} RegisterServiceProviderSyscall; - -typedef struct { - Syscall; - char *serviceName; - char *providerName; - uint32_t dataSize; - void *data; -} RequestSyscall; - -typedef struct { - Syscall; - uint16_t port; - uint8_t size; -} IOPortSyscall; - -typedef struct { - IOPortSyscall; - uint32_t result; -} IOPortInSyscall; - -typedef struct { - IOPortSyscall; - uint32_t value; -} IOPortOutSyscall; - -typedef struct { - Syscall; - char *programName; -} LoadFromInitrdSyscall; - #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 49ac65c..a70cf75 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -22,20 +22,17 @@ Provider *provider = findProvider(service, "main"); Syscall *runTask = malloc(sizeof(Syscall)); runTask->function = SYS_RUN; - runTask->address = provider->address; runTask->resume = true; runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); runTask->esp = malloc(0x1000); runTask->respondingTo = respondingTo; runTask->service = service; memset(runTask->esp, 0, 0x1000); - runTask->esp += 0xFFC; - *(void **)runTask->esp = &runEnd; + runTask->esp += 0xFF8; + *(void **)runTask->esp = provider->address; + *(void **)(runTask->esp + 4) = &runEnd; sharePage(&service->pagingInfo, runTask->esp, runTask->esp); listAdd(&callsToProcess, runTask); - if (!runTask->address) { - asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); - } return runTask; } @@ -68,8 +65,6 @@ call->resume = true; if (!call->avoidReschedule) { listAdd(&callsToProcess, call); - void *temporary = mapTemporary(call->writeBack); - memcpy(call, temporary, sizeof(IOPortInSyscall)); } } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index e715905..c6aa5f9 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -15,7 +15,9 @@ block->allocatedCoarse &= ~(1 << coarse); break; } - return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + void *result = ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + memset(result, 0, block->blockSize); + return result; } void *malloc(uint32_t size) { diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index f538328..9c47365 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -2,7 +2,7 @@ global runFunction global runEnd -global runEndSyscall +global temporaryESP extern currentSyscall @@ -13,17 +13,17 @@ mov eax, esp mov [temporaryESP], eax mov ebx, [currentSyscall] - mov ecx, [ebx + 8] + mov ecx, [ebx + 24] mov ebp, ecx - mov edx, [ebx + 4] - mov eax, [ebx + 12] + mov edx, returnPoint + mov eax, [ebx + 28] + mov ebx, [ebx + 20] mov cr3, eax + mov eax, ebx sysexit runEnd: mov eax, 0 sysenter -runEndSyscall: - mov eax, [temporaryESP] - mov esp, eax - pop ebp + +returnPoint: ret diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index 450b4b2..a61ff1d 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -13,9 +13,6 @@ void resume(Syscall *syscall) { currentSyscall = syscall; - if (!syscall->address) { - asm("hlt" ::"a"(syscall)); - } runFunction(); } diff --git a/src/include/syscalls.h b/src/include/syscalls.h index e52e178..2a35dd8 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -11,53 +11,20 @@ SYS_IO_IN = 3, SYS_IO_OUT = 4, SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_PROVIDER = 7, } SyscallIds; typedef struct Syscall { uint32_t function; - void *address; + uint32_t parameters[4]; + uint32_t returnValue; void *esp; void *cr3; struct Syscall *respondingTo; void *service; bool resume; bool avoidReschedule; - struct Syscall *writeBack; } Syscall; -typedef struct { - Syscall; - void *handler; - char *name; -} RegisterServiceProviderSyscall; - -typedef struct { - Syscall; - char *serviceName; - char *providerName; - uint32_t dataSize; - void *data; -} RequestSyscall; - -typedef struct { - Syscall; - uint16_t port; - uint8_t size; -} IOPortSyscall; - -typedef struct { - IOPortSyscall; - uint32_t result; -} IOPortInSyscall; - -typedef struct { - IOPortSyscall; - uint32_t value; -} IOPortOutSyscall; - -typedef struct { - Syscall; - char *programName; -} LoadFromInitrdSyscall; - #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 49ac65c..a70cf75 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -22,20 +22,17 @@ Provider *provider = findProvider(service, "main"); Syscall *runTask = malloc(sizeof(Syscall)); runTask->function = SYS_RUN; - runTask->address = provider->address; runTask->resume = true; runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); runTask->esp = malloc(0x1000); runTask->respondingTo = respondingTo; runTask->service = service; memset(runTask->esp, 0, 0x1000); - runTask->esp += 0xFFC; - *(void **)runTask->esp = &runEnd; + runTask->esp += 0xFF8; + *(void **)runTask->esp = provider->address; + *(void **)(runTask->esp + 4) = &runEnd; sharePage(&service->pagingInfo, runTask->esp, runTask->esp); listAdd(&callsToProcess, runTask); - if (!runTask->address) { - asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); - } return runTask; } @@ -68,8 +65,6 @@ call->resume = true; if (!call->avoidReschedule) { listAdd(&callsToProcess, call); - void *temporary = mapTemporary(call->writeBack); - memcpy(call, temporary, sizeof(IOPortInSyscall)); } } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index e715905..c6aa5f9 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -15,7 +15,9 @@ block->allocatedCoarse &= ~(1 << coarse); break; } - return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + void *result = ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + memset(result, 0, block->blockSize); + return result; } void *malloc(uint32_t size) { diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index f538328..9c47365 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -2,7 +2,7 @@ global runFunction global runEnd -global runEndSyscall +global temporaryESP extern currentSyscall @@ -13,17 +13,17 @@ mov eax, esp mov [temporaryESP], eax mov ebx, [currentSyscall] - mov ecx, [ebx + 8] + mov ecx, [ebx + 24] mov ebp, ecx - mov edx, [ebx + 4] - mov eax, [ebx + 12] + mov edx, returnPoint + mov eax, [ebx + 28] + mov ebx, [ebx + 20] mov cr3, eax + mov eax, ebx sysexit runEnd: mov eax, 0 sysenter -runEndSyscall: - mov eax, [temporaryESP] - mov esp, eax - pop ebp + +returnPoint: ret diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index 450b4b2..a61ff1d 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -13,9 +13,6 @@ void resume(Syscall *syscall) { currentSyscall = syscall; - if (!syscall->address) { - asm("hlt" ::"a"(syscall)); - } runFunction(); } diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 51dd4c4..541cea0 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -5,7 +5,6 @@ #include #include -extern void *runEndSyscall; extern ListElement *callsToProcess; extern void(syscallStub)(); extern Syscall *currentSyscall; @@ -19,30 +18,30 @@ 0); // when transitioning to 64 bit: U32(value) >> 32); } -void handleSyscall(void *cr3, Syscall *callData) { - if (!callData) { +void handleSyscall(void *esp, uint32_t function, uint32_t parameter0, + uint32_t parameter1, uint32_t parameter2, + uint32_t parameter3) { + if (!function) { if (currentSyscall->respondingTo) { listAdd(&callsToProcess, currentSyscall->respondingTo); } - asm("jmp runEndSyscall"); + return; } - Service *service = currentSyscall->service; - void *dataPhysical = - getPhysicalAddress(service->pagingInfo.pageDirectory, callData); - Syscall *call = malloc(sizeof(RequestSyscall)); - void *data = mapTemporary(dataPhysical); - memcpy(data, call, sizeof(RequestSyscall)); - call->cr3 = cr3; + Syscall *call = malloc(sizeof(Syscall)); + call->function = function; + call->parameters[0] = parameter0; + call->parameters[1] = parameter1; + call->parameters[2] = parameter2; + call->parameters[3] = parameter3; call->service = currentSyscall->service; - call->writeBack = dataPhysical; + call->esp = esp; if (!call->respondingTo) { call->respondingTo = currentSyscall->respondingTo; } - if (!call->address) { - asm("hlt" ::"a"(call), "b"(dataPhysical)); - } + Service *currentService = currentSyscall->service; + call->cr3 = + getPhysicalAddressKernel(currentService->pagingInfo.pageDirectory); listAdd(&callsToProcess, call); - asm("jmp runEndSyscall"); } void *syscallStubPtr = syscallStub; @@ -53,28 +52,33 @@ writeMsrRegister(0x176, syscallStubPtr); // the handler } -void handleInstallSyscall(RegisterServiceProviderSyscall *call) { +void handleInstallSyscall(Syscall *call) { Provider *provider = malloc(sizeof(Provider)); Service *service = call->service; - char *providerName = kernelMapPhysical( - getPhysicalAddress(service->pagingInfo.pageDirectory, call->name)); + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); provider->name = providerName; - provider->address = call->handler; + provider->address = PTR(call->parameters[1]); provider->service = call->service; listAdd(&service->providers, provider); } -void handleRequestSyscall(RequestSyscall *call) { +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +extern ListElement *services; + +void handleRequestSyscall(Syscall *call) { Service *service = call->service; - char *serviceName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->serviceName)); - Service *providerService = findService(serviceName); - char *providerName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->providerName)); - Provider *callProvider = findProvider(providerService, providerName); + Service *providerService = listGet(services, call->parameters[0]); + Provider *provider = + listGet(providerService->providers, call->parameters[1]); Syscall *runCall = malloc(sizeof(Syscall)); runCall->function = SYS_RUN; - runCall->address = callProvider->address; runCall->esp = malloc(0x1000); runCall->respondingTo = (void *)call; runCall->cr3 = @@ -82,50 +86,94 @@ runCall->service = providerService; runCall->resume = true; sharePage(&providerService->pagingInfo, runCall->esp, runCall->esp); - runCall->esp += 0xFFC; - *(void **)runCall->esp = &runEnd; + runCall->esp += 0xFF8; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 4) = &runEnd; listAdd(&callsToProcess, runCall); call->avoidReschedule = true; } -void handleIOInSyscall(IOPortInSyscall *call) { - switch (call->size) { +void handleIOInSyscall(Syscall *call) { + switch (call->parameters[0]) { case 1: - asm("in %%dx, %%al" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%al" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; case 2: - asm("in %%dx, %%ax" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%ax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; case 4: - asm("in %%dx, %%eax" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%eax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; } } -void handleIOOutSyscall(IOPortOutSyscall *call) { - switch (call->size) { +void handleIOOutSyscall(Syscall *call) { + switch (call->parameters[0]) { case 1: - asm("out %0, %1" : : "a"((uint8_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint8_t)call->parameters[2]), "Nd"(call->parameters[1])); break; case 2: - asm("out %0, %1" : : "a"((uint16_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint16_t)call->parameters[2]), "Nd"(call->parameters[1])); break; case 4: - asm("out %0, %1" : : "a"((uint32_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint32_t)call->parameters[2]), "Nd"(call->parameters[1])); break; } } extern Syscall *loadInitrdProgram(char *name, Syscall *respondingTo); -void handleLoadFromInitrdSyscall(LoadFromInitrdSyscall *call) { +void handleLoadFromInitrdSyscall(Syscall *call) { Service *service = call->service; char *programName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->programName)); + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); loadInitrdProgram(programName, (void *)call); call->avoidReschedule = true; } +void handleGetServiceSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleGetProviderSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *providerService = listGet(services, call->parameters[0]); + foreach (providerService->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + void (*syscallHandlers[])(Syscall *) = { 0, (void *)handleInstallSyscall, @@ -133,4 +181,6 @@ (void *)handleIOInSyscall, (void *)handleIOOutSyscall, (void *)handleLoadFromInitrdSyscall, + (void *)handleGetServiceSyscall, + (void *)handleGetProviderSyscall, }; diff --git a/src/include/syscalls.h b/src/include/syscalls.h index e52e178..2a35dd8 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -11,53 +11,20 @@ SYS_IO_IN = 3, SYS_IO_OUT = 4, SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_PROVIDER = 7, } SyscallIds; typedef struct Syscall { uint32_t function; - void *address; + uint32_t parameters[4]; + uint32_t returnValue; void *esp; void *cr3; struct Syscall *respondingTo; void *service; bool resume; bool avoidReschedule; - struct Syscall *writeBack; } Syscall; -typedef struct { - Syscall; - void *handler; - char *name; -} RegisterServiceProviderSyscall; - -typedef struct { - Syscall; - char *serviceName; - char *providerName; - uint32_t dataSize; - void *data; -} RequestSyscall; - -typedef struct { - Syscall; - uint16_t port; - uint8_t size; -} IOPortSyscall; - -typedef struct { - IOPortSyscall; - uint32_t result; -} IOPortInSyscall; - -typedef struct { - IOPortSyscall; - uint32_t value; -} IOPortOutSyscall; - -typedef struct { - Syscall; - char *programName; -} LoadFromInitrdSyscall; - #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 49ac65c..a70cf75 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -22,20 +22,17 @@ Provider *provider = findProvider(service, "main"); Syscall *runTask = malloc(sizeof(Syscall)); runTask->function = SYS_RUN; - runTask->address = provider->address; runTask->resume = true; runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); runTask->esp = malloc(0x1000); runTask->respondingTo = respondingTo; runTask->service = service; memset(runTask->esp, 0, 0x1000); - runTask->esp += 0xFFC; - *(void **)runTask->esp = &runEnd; + runTask->esp += 0xFF8; + *(void **)runTask->esp = provider->address; + *(void **)(runTask->esp + 4) = &runEnd; sharePage(&service->pagingInfo, runTask->esp, runTask->esp); listAdd(&callsToProcess, runTask); - if (!runTask->address) { - asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); - } return runTask; } @@ -68,8 +65,6 @@ call->resume = true; if (!call->avoidReschedule) { listAdd(&callsToProcess, call); - void *temporary = mapTemporary(call->writeBack); - memcpy(call, temporary, sizeof(IOPortInSyscall)); } } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index e715905..c6aa5f9 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -15,7 +15,9 @@ block->allocatedCoarse &= ~(1 << coarse); break; } - return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + void *result = ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + memset(result, 0, block->blockSize); + return result; } void *malloc(uint32_t size) { diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index f538328..9c47365 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -2,7 +2,7 @@ global runFunction global runEnd -global runEndSyscall +global temporaryESP extern currentSyscall @@ -13,17 +13,17 @@ mov eax, esp mov [temporaryESP], eax mov ebx, [currentSyscall] - mov ecx, [ebx + 8] + mov ecx, [ebx + 24] mov ebp, ecx - mov edx, [ebx + 4] - mov eax, [ebx + 12] + mov edx, returnPoint + mov eax, [ebx + 28] + mov ebx, [ebx + 20] mov cr3, eax + mov eax, ebx sysexit runEnd: mov eax, 0 sysenter -runEndSyscall: - mov eax, [temporaryESP] - mov esp, eax - pop ebp + +returnPoint: ret diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index 450b4b2..a61ff1d 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -13,9 +13,6 @@ void resume(Syscall *syscall) { currentSyscall = syscall; - if (!syscall->address) { - asm("hlt" ::"a"(syscall)); - } runFunction(); } diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 51dd4c4..541cea0 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -5,7 +5,6 @@ #include #include -extern void *runEndSyscall; extern ListElement *callsToProcess; extern void(syscallStub)(); extern Syscall *currentSyscall; @@ -19,30 +18,30 @@ 0); // when transitioning to 64 bit: U32(value) >> 32); } -void handleSyscall(void *cr3, Syscall *callData) { - if (!callData) { +void handleSyscall(void *esp, uint32_t function, uint32_t parameter0, + uint32_t parameter1, uint32_t parameter2, + uint32_t parameter3) { + if (!function) { if (currentSyscall->respondingTo) { listAdd(&callsToProcess, currentSyscall->respondingTo); } - asm("jmp runEndSyscall"); + return; } - Service *service = currentSyscall->service; - void *dataPhysical = - getPhysicalAddress(service->pagingInfo.pageDirectory, callData); - Syscall *call = malloc(sizeof(RequestSyscall)); - void *data = mapTemporary(dataPhysical); - memcpy(data, call, sizeof(RequestSyscall)); - call->cr3 = cr3; + Syscall *call = malloc(sizeof(Syscall)); + call->function = function; + call->parameters[0] = parameter0; + call->parameters[1] = parameter1; + call->parameters[2] = parameter2; + call->parameters[3] = parameter3; call->service = currentSyscall->service; - call->writeBack = dataPhysical; + call->esp = esp; if (!call->respondingTo) { call->respondingTo = currentSyscall->respondingTo; } - if (!call->address) { - asm("hlt" ::"a"(call), "b"(dataPhysical)); - } + Service *currentService = currentSyscall->service; + call->cr3 = + getPhysicalAddressKernel(currentService->pagingInfo.pageDirectory); listAdd(&callsToProcess, call); - asm("jmp runEndSyscall"); } void *syscallStubPtr = syscallStub; @@ -53,28 +52,33 @@ writeMsrRegister(0x176, syscallStubPtr); // the handler } -void handleInstallSyscall(RegisterServiceProviderSyscall *call) { +void handleInstallSyscall(Syscall *call) { Provider *provider = malloc(sizeof(Provider)); Service *service = call->service; - char *providerName = kernelMapPhysical( - getPhysicalAddress(service->pagingInfo.pageDirectory, call->name)); + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); provider->name = providerName; - provider->address = call->handler; + provider->address = PTR(call->parameters[1]); provider->service = call->service; listAdd(&service->providers, provider); } -void handleRequestSyscall(RequestSyscall *call) { +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +extern ListElement *services; + +void handleRequestSyscall(Syscall *call) { Service *service = call->service; - char *serviceName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->serviceName)); - Service *providerService = findService(serviceName); - char *providerName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->providerName)); - Provider *callProvider = findProvider(providerService, providerName); + Service *providerService = listGet(services, call->parameters[0]); + Provider *provider = + listGet(providerService->providers, call->parameters[1]); Syscall *runCall = malloc(sizeof(Syscall)); runCall->function = SYS_RUN; - runCall->address = callProvider->address; runCall->esp = malloc(0x1000); runCall->respondingTo = (void *)call; runCall->cr3 = @@ -82,50 +86,94 @@ runCall->service = providerService; runCall->resume = true; sharePage(&providerService->pagingInfo, runCall->esp, runCall->esp); - runCall->esp += 0xFFC; - *(void **)runCall->esp = &runEnd; + runCall->esp += 0xFF8; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 4) = &runEnd; listAdd(&callsToProcess, runCall); call->avoidReschedule = true; } -void handleIOInSyscall(IOPortInSyscall *call) { - switch (call->size) { +void handleIOInSyscall(Syscall *call) { + switch (call->parameters[0]) { case 1: - asm("in %%dx, %%al" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%al" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; case 2: - asm("in %%dx, %%ax" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%ax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; case 4: - asm("in %%dx, %%eax" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%eax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; } } -void handleIOOutSyscall(IOPortOutSyscall *call) { - switch (call->size) { +void handleIOOutSyscall(Syscall *call) { + switch (call->parameters[0]) { case 1: - asm("out %0, %1" : : "a"((uint8_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint8_t)call->parameters[2]), "Nd"(call->parameters[1])); break; case 2: - asm("out %0, %1" : : "a"((uint16_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint16_t)call->parameters[2]), "Nd"(call->parameters[1])); break; case 4: - asm("out %0, %1" : : "a"((uint32_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint32_t)call->parameters[2]), "Nd"(call->parameters[1])); break; } } extern Syscall *loadInitrdProgram(char *name, Syscall *respondingTo); -void handleLoadFromInitrdSyscall(LoadFromInitrdSyscall *call) { +void handleLoadFromInitrdSyscall(Syscall *call) { Service *service = call->service; char *programName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->programName)); + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); loadInitrdProgram(programName, (void *)call); call->avoidReschedule = true; } +void handleGetServiceSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleGetProviderSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *providerService = listGet(services, call->parameters[0]); + foreach (providerService->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + void (*syscallHandlers[])(Syscall *) = { 0, (void *)handleInstallSyscall, @@ -133,4 +181,6 @@ (void *)handleIOInSyscall, (void *)handleIOOutSyscall, (void *)handleLoadFromInitrdSyscall, + (void *)handleGetServiceSyscall, + (void *)handleGetProviderSyscall, }; diff --git a/src/kernel/syscalls/syscallStub.asm b/src/kernel/syscalls/syscallStub.asm index ad29d6e..f8213a8 100644 --- a/src/kernel/syscalls/syscallStub.asm +++ b/src/kernel/syscalls/syscallStub.asm @@ -3,16 +3,23 @@ global syscallStub extern handleSyscall +extern temporaryESP + +temporaryEAX: resb 4 syscallStub: - mov ebx, cr3 - mov ecx, 0x500000 - mov cr3, ecx - push eax + mov [temporaryEAX], eax + mov eax, 0x500000 + mov cr3, eax + mov eax, [temporaryEAX] + push esi + push edx + push ecx push ebx + push eax + push edi call handleSyscall - pop ebx - mov edx, [eax+4] - mov ecx, [eax+8] - mov cr3, ebx - sysexit + mov eax, [temporaryESP] + mov esp, eax + pop ebp + ret diff --git a/src/include/syscalls.h b/src/include/syscalls.h index e52e178..2a35dd8 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -11,53 +11,20 @@ SYS_IO_IN = 3, SYS_IO_OUT = 4, SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_PROVIDER = 7, } SyscallIds; typedef struct Syscall { uint32_t function; - void *address; + uint32_t parameters[4]; + uint32_t returnValue; void *esp; void *cr3; struct Syscall *respondingTo; void *service; bool resume; bool avoidReschedule; - struct Syscall *writeBack; } Syscall; -typedef struct { - Syscall; - void *handler; - char *name; -} RegisterServiceProviderSyscall; - -typedef struct { - Syscall; - char *serviceName; - char *providerName; - uint32_t dataSize; - void *data; -} RequestSyscall; - -typedef struct { - Syscall; - uint16_t port; - uint8_t size; -} IOPortSyscall; - -typedef struct { - IOPortSyscall; - uint32_t result; -} IOPortInSyscall; - -typedef struct { - IOPortSyscall; - uint32_t value; -} IOPortOutSyscall; - -typedef struct { - Syscall; - char *programName; -} LoadFromInitrdSyscall; - #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 49ac65c..a70cf75 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -22,20 +22,17 @@ Provider *provider = findProvider(service, "main"); Syscall *runTask = malloc(sizeof(Syscall)); runTask->function = SYS_RUN; - runTask->address = provider->address; runTask->resume = true; runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); runTask->esp = malloc(0x1000); runTask->respondingTo = respondingTo; runTask->service = service; memset(runTask->esp, 0, 0x1000); - runTask->esp += 0xFFC; - *(void **)runTask->esp = &runEnd; + runTask->esp += 0xFF8; + *(void **)runTask->esp = provider->address; + *(void **)(runTask->esp + 4) = &runEnd; sharePage(&service->pagingInfo, runTask->esp, runTask->esp); listAdd(&callsToProcess, runTask); - if (!runTask->address) { - asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); - } return runTask; } @@ -68,8 +65,6 @@ call->resume = true; if (!call->avoidReschedule) { listAdd(&callsToProcess, call); - void *temporary = mapTemporary(call->writeBack); - memcpy(call, temporary, sizeof(IOPortInSyscall)); } } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index e715905..c6aa5f9 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -15,7 +15,9 @@ block->allocatedCoarse &= ~(1 << coarse); break; } - return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + void *result = ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + memset(result, 0, block->blockSize); + return result; } void *malloc(uint32_t size) { diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index f538328..9c47365 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -2,7 +2,7 @@ global runFunction global runEnd -global runEndSyscall +global temporaryESP extern currentSyscall @@ -13,17 +13,17 @@ mov eax, esp mov [temporaryESP], eax mov ebx, [currentSyscall] - mov ecx, [ebx + 8] + mov ecx, [ebx + 24] mov ebp, ecx - mov edx, [ebx + 4] - mov eax, [ebx + 12] + mov edx, returnPoint + mov eax, [ebx + 28] + mov ebx, [ebx + 20] mov cr3, eax + mov eax, ebx sysexit runEnd: mov eax, 0 sysenter -runEndSyscall: - mov eax, [temporaryESP] - mov esp, eax - pop ebp + +returnPoint: ret diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index 450b4b2..a61ff1d 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -13,9 +13,6 @@ void resume(Syscall *syscall) { currentSyscall = syscall; - if (!syscall->address) { - asm("hlt" ::"a"(syscall)); - } runFunction(); } diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 51dd4c4..541cea0 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -5,7 +5,6 @@ #include #include -extern void *runEndSyscall; extern ListElement *callsToProcess; extern void(syscallStub)(); extern Syscall *currentSyscall; @@ -19,30 +18,30 @@ 0); // when transitioning to 64 bit: U32(value) >> 32); } -void handleSyscall(void *cr3, Syscall *callData) { - if (!callData) { +void handleSyscall(void *esp, uint32_t function, uint32_t parameter0, + uint32_t parameter1, uint32_t parameter2, + uint32_t parameter3) { + if (!function) { if (currentSyscall->respondingTo) { listAdd(&callsToProcess, currentSyscall->respondingTo); } - asm("jmp runEndSyscall"); + return; } - Service *service = currentSyscall->service; - void *dataPhysical = - getPhysicalAddress(service->pagingInfo.pageDirectory, callData); - Syscall *call = malloc(sizeof(RequestSyscall)); - void *data = mapTemporary(dataPhysical); - memcpy(data, call, sizeof(RequestSyscall)); - call->cr3 = cr3; + Syscall *call = malloc(sizeof(Syscall)); + call->function = function; + call->parameters[0] = parameter0; + call->parameters[1] = parameter1; + call->parameters[2] = parameter2; + call->parameters[3] = parameter3; call->service = currentSyscall->service; - call->writeBack = dataPhysical; + call->esp = esp; if (!call->respondingTo) { call->respondingTo = currentSyscall->respondingTo; } - if (!call->address) { - asm("hlt" ::"a"(call), "b"(dataPhysical)); - } + Service *currentService = currentSyscall->service; + call->cr3 = + getPhysicalAddressKernel(currentService->pagingInfo.pageDirectory); listAdd(&callsToProcess, call); - asm("jmp runEndSyscall"); } void *syscallStubPtr = syscallStub; @@ -53,28 +52,33 @@ writeMsrRegister(0x176, syscallStubPtr); // the handler } -void handleInstallSyscall(RegisterServiceProviderSyscall *call) { +void handleInstallSyscall(Syscall *call) { Provider *provider = malloc(sizeof(Provider)); Service *service = call->service; - char *providerName = kernelMapPhysical( - getPhysicalAddress(service->pagingInfo.pageDirectory, call->name)); + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); provider->name = providerName; - provider->address = call->handler; + provider->address = PTR(call->parameters[1]); provider->service = call->service; listAdd(&service->providers, provider); } -void handleRequestSyscall(RequestSyscall *call) { +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +extern ListElement *services; + +void handleRequestSyscall(Syscall *call) { Service *service = call->service; - char *serviceName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->serviceName)); - Service *providerService = findService(serviceName); - char *providerName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->providerName)); - Provider *callProvider = findProvider(providerService, providerName); + Service *providerService = listGet(services, call->parameters[0]); + Provider *provider = + listGet(providerService->providers, call->parameters[1]); Syscall *runCall = malloc(sizeof(Syscall)); runCall->function = SYS_RUN; - runCall->address = callProvider->address; runCall->esp = malloc(0x1000); runCall->respondingTo = (void *)call; runCall->cr3 = @@ -82,50 +86,94 @@ runCall->service = providerService; runCall->resume = true; sharePage(&providerService->pagingInfo, runCall->esp, runCall->esp); - runCall->esp += 0xFFC; - *(void **)runCall->esp = &runEnd; + runCall->esp += 0xFF8; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 4) = &runEnd; listAdd(&callsToProcess, runCall); call->avoidReschedule = true; } -void handleIOInSyscall(IOPortInSyscall *call) { - switch (call->size) { +void handleIOInSyscall(Syscall *call) { + switch (call->parameters[0]) { case 1: - asm("in %%dx, %%al" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%al" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; case 2: - asm("in %%dx, %%ax" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%ax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; case 4: - asm("in %%dx, %%eax" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%eax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; } } -void handleIOOutSyscall(IOPortOutSyscall *call) { - switch (call->size) { +void handleIOOutSyscall(Syscall *call) { + switch (call->parameters[0]) { case 1: - asm("out %0, %1" : : "a"((uint8_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint8_t)call->parameters[2]), "Nd"(call->parameters[1])); break; case 2: - asm("out %0, %1" : : "a"((uint16_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint16_t)call->parameters[2]), "Nd"(call->parameters[1])); break; case 4: - asm("out %0, %1" : : "a"((uint32_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint32_t)call->parameters[2]), "Nd"(call->parameters[1])); break; } } extern Syscall *loadInitrdProgram(char *name, Syscall *respondingTo); -void handleLoadFromInitrdSyscall(LoadFromInitrdSyscall *call) { +void handleLoadFromInitrdSyscall(Syscall *call) { Service *service = call->service; char *programName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->programName)); + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); loadInitrdProgram(programName, (void *)call); call->avoidReschedule = true; } +void handleGetServiceSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleGetProviderSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *providerService = listGet(services, call->parameters[0]); + foreach (providerService->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + void (*syscallHandlers[])(Syscall *) = { 0, (void *)handleInstallSyscall, @@ -133,4 +181,6 @@ (void *)handleIOInSyscall, (void *)handleIOOutSyscall, (void *)handleLoadFromInitrdSyscall, + (void *)handleGetServiceSyscall, + (void *)handleGetProviderSyscall, }; diff --git a/src/kernel/syscalls/syscallStub.asm b/src/kernel/syscalls/syscallStub.asm index ad29d6e..f8213a8 100644 --- a/src/kernel/syscalls/syscallStub.asm +++ b/src/kernel/syscalls/syscallStub.asm @@ -3,16 +3,23 @@ global syscallStub extern handleSyscall +extern temporaryESP + +temporaryEAX: resb 4 syscallStub: - mov ebx, cr3 - mov ecx, 0x500000 - mov cr3, ecx - push eax + mov [temporaryEAX], eax + mov eax, 0x500000 + mov cr3, eax + mov eax, [temporaryEAX] + push esi + push edx + push ecx push ebx + push eax + push edi call handleSyscall - pop ebx - mov edx, [eax+4] - mov ecx, [eax+8] - mov cr3, ebx - sysexit + mov eax, [temporaryESP] + mov esp, eax + pop ebp + ret diff --git a/src/kernel/util/list.c b/src/kernel/util/list.c index aa04956..a5f39fb 100644 --- a/src/kernel/util/list.c +++ b/src/kernel/util/list.c @@ -3,9 +3,17 @@ void listAdd(ListElement **list, void *data) { ListElement *element = malloc(sizeof(ListElement)); - element->next = *list; element->data = data; - *list = element; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; } void *listPopFirst(ListElement **list) { diff --git a/src/include/syscalls.h b/src/include/syscalls.h index e52e178..2a35dd8 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -11,53 +11,20 @@ SYS_IO_IN = 3, SYS_IO_OUT = 4, SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_PROVIDER = 7, } SyscallIds; typedef struct Syscall { uint32_t function; - void *address; + uint32_t parameters[4]; + uint32_t returnValue; void *esp; void *cr3; struct Syscall *respondingTo; void *service; bool resume; bool avoidReschedule; - struct Syscall *writeBack; } Syscall; -typedef struct { - Syscall; - void *handler; - char *name; -} RegisterServiceProviderSyscall; - -typedef struct { - Syscall; - char *serviceName; - char *providerName; - uint32_t dataSize; - void *data; -} RequestSyscall; - -typedef struct { - Syscall; - uint16_t port; - uint8_t size; -} IOPortSyscall; - -typedef struct { - IOPortSyscall; - uint32_t result; -} IOPortInSyscall; - -typedef struct { - IOPortSyscall; - uint32_t value; -} IOPortOutSyscall; - -typedef struct { - Syscall; - char *programName; -} LoadFromInitrdSyscall; - #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 49ac65c..a70cf75 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -22,20 +22,17 @@ Provider *provider = findProvider(service, "main"); Syscall *runTask = malloc(sizeof(Syscall)); runTask->function = SYS_RUN; - runTask->address = provider->address; runTask->resume = true; runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); runTask->esp = malloc(0x1000); runTask->respondingTo = respondingTo; runTask->service = service; memset(runTask->esp, 0, 0x1000); - runTask->esp += 0xFFC; - *(void **)runTask->esp = &runEnd; + runTask->esp += 0xFF8; + *(void **)runTask->esp = provider->address; + *(void **)(runTask->esp + 4) = &runEnd; sharePage(&service->pagingInfo, runTask->esp, runTask->esp); listAdd(&callsToProcess, runTask); - if (!runTask->address) { - asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); - } return runTask; } @@ -68,8 +65,6 @@ call->resume = true; if (!call->avoidReschedule) { listAdd(&callsToProcess, call); - void *temporary = mapTemporary(call->writeBack); - memcpy(call, temporary, sizeof(IOPortInSyscall)); } } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index e715905..c6aa5f9 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -15,7 +15,9 @@ block->allocatedCoarse &= ~(1 << coarse); break; } - return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + void *result = ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + memset(result, 0, block->blockSize); + return result; } void *malloc(uint32_t size) { diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index f538328..9c47365 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -2,7 +2,7 @@ global runFunction global runEnd -global runEndSyscall +global temporaryESP extern currentSyscall @@ -13,17 +13,17 @@ mov eax, esp mov [temporaryESP], eax mov ebx, [currentSyscall] - mov ecx, [ebx + 8] + mov ecx, [ebx + 24] mov ebp, ecx - mov edx, [ebx + 4] - mov eax, [ebx + 12] + mov edx, returnPoint + mov eax, [ebx + 28] + mov ebx, [ebx + 20] mov cr3, eax + mov eax, ebx sysexit runEnd: mov eax, 0 sysenter -runEndSyscall: - mov eax, [temporaryESP] - mov esp, eax - pop ebp + +returnPoint: ret diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index 450b4b2..a61ff1d 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -13,9 +13,6 @@ void resume(Syscall *syscall) { currentSyscall = syscall; - if (!syscall->address) { - asm("hlt" ::"a"(syscall)); - } runFunction(); } diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 51dd4c4..541cea0 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -5,7 +5,6 @@ #include #include -extern void *runEndSyscall; extern ListElement *callsToProcess; extern void(syscallStub)(); extern Syscall *currentSyscall; @@ -19,30 +18,30 @@ 0); // when transitioning to 64 bit: U32(value) >> 32); } -void handleSyscall(void *cr3, Syscall *callData) { - if (!callData) { +void handleSyscall(void *esp, uint32_t function, uint32_t parameter0, + uint32_t parameter1, uint32_t parameter2, + uint32_t parameter3) { + if (!function) { if (currentSyscall->respondingTo) { listAdd(&callsToProcess, currentSyscall->respondingTo); } - asm("jmp runEndSyscall"); + return; } - Service *service = currentSyscall->service; - void *dataPhysical = - getPhysicalAddress(service->pagingInfo.pageDirectory, callData); - Syscall *call = malloc(sizeof(RequestSyscall)); - void *data = mapTemporary(dataPhysical); - memcpy(data, call, sizeof(RequestSyscall)); - call->cr3 = cr3; + Syscall *call = malloc(sizeof(Syscall)); + call->function = function; + call->parameters[0] = parameter0; + call->parameters[1] = parameter1; + call->parameters[2] = parameter2; + call->parameters[3] = parameter3; call->service = currentSyscall->service; - call->writeBack = dataPhysical; + call->esp = esp; if (!call->respondingTo) { call->respondingTo = currentSyscall->respondingTo; } - if (!call->address) { - asm("hlt" ::"a"(call), "b"(dataPhysical)); - } + Service *currentService = currentSyscall->service; + call->cr3 = + getPhysicalAddressKernel(currentService->pagingInfo.pageDirectory); listAdd(&callsToProcess, call); - asm("jmp runEndSyscall"); } void *syscallStubPtr = syscallStub; @@ -53,28 +52,33 @@ writeMsrRegister(0x176, syscallStubPtr); // the handler } -void handleInstallSyscall(RegisterServiceProviderSyscall *call) { +void handleInstallSyscall(Syscall *call) { Provider *provider = malloc(sizeof(Provider)); Service *service = call->service; - char *providerName = kernelMapPhysical( - getPhysicalAddress(service->pagingInfo.pageDirectory, call->name)); + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); provider->name = providerName; - provider->address = call->handler; + provider->address = PTR(call->parameters[1]); provider->service = call->service; listAdd(&service->providers, provider); } -void handleRequestSyscall(RequestSyscall *call) { +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +extern ListElement *services; + +void handleRequestSyscall(Syscall *call) { Service *service = call->service; - char *serviceName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->serviceName)); - Service *providerService = findService(serviceName); - char *providerName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->providerName)); - Provider *callProvider = findProvider(providerService, providerName); + Service *providerService = listGet(services, call->parameters[0]); + Provider *provider = + listGet(providerService->providers, call->parameters[1]); Syscall *runCall = malloc(sizeof(Syscall)); runCall->function = SYS_RUN; - runCall->address = callProvider->address; runCall->esp = malloc(0x1000); runCall->respondingTo = (void *)call; runCall->cr3 = @@ -82,50 +86,94 @@ runCall->service = providerService; runCall->resume = true; sharePage(&providerService->pagingInfo, runCall->esp, runCall->esp); - runCall->esp += 0xFFC; - *(void **)runCall->esp = &runEnd; + runCall->esp += 0xFF8; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 4) = &runEnd; listAdd(&callsToProcess, runCall); call->avoidReschedule = true; } -void handleIOInSyscall(IOPortInSyscall *call) { - switch (call->size) { +void handleIOInSyscall(Syscall *call) { + switch (call->parameters[0]) { case 1: - asm("in %%dx, %%al" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%al" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; case 2: - asm("in %%dx, %%ax" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%ax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; case 4: - asm("in %%dx, %%eax" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%eax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; } } -void handleIOOutSyscall(IOPortOutSyscall *call) { - switch (call->size) { +void handleIOOutSyscall(Syscall *call) { + switch (call->parameters[0]) { case 1: - asm("out %0, %1" : : "a"((uint8_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint8_t)call->parameters[2]), "Nd"(call->parameters[1])); break; case 2: - asm("out %0, %1" : : "a"((uint16_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint16_t)call->parameters[2]), "Nd"(call->parameters[1])); break; case 4: - asm("out %0, %1" : : "a"((uint32_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint32_t)call->parameters[2]), "Nd"(call->parameters[1])); break; } } extern Syscall *loadInitrdProgram(char *name, Syscall *respondingTo); -void handleLoadFromInitrdSyscall(LoadFromInitrdSyscall *call) { +void handleLoadFromInitrdSyscall(Syscall *call) { Service *service = call->service; char *programName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->programName)); + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); loadInitrdProgram(programName, (void *)call); call->avoidReschedule = true; } +void handleGetServiceSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleGetProviderSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *providerService = listGet(services, call->parameters[0]); + foreach (providerService->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + void (*syscallHandlers[])(Syscall *) = { 0, (void *)handleInstallSyscall, @@ -133,4 +181,6 @@ (void *)handleIOInSyscall, (void *)handleIOOutSyscall, (void *)handleLoadFromInitrdSyscall, + (void *)handleGetServiceSyscall, + (void *)handleGetProviderSyscall, }; diff --git a/src/kernel/syscalls/syscallStub.asm b/src/kernel/syscalls/syscallStub.asm index ad29d6e..f8213a8 100644 --- a/src/kernel/syscalls/syscallStub.asm +++ b/src/kernel/syscalls/syscallStub.asm @@ -3,16 +3,23 @@ global syscallStub extern handleSyscall +extern temporaryESP + +temporaryEAX: resb 4 syscallStub: - mov ebx, cr3 - mov ecx, 0x500000 - mov cr3, ecx - push eax + mov [temporaryEAX], eax + mov eax, 0x500000 + mov cr3, eax + mov eax, [temporaryEAX] + push esi + push edx + push ecx push ebx + push eax + push edi call handleSyscall - pop ebx - mov edx, [eax+4] - mov ecx, [eax+8] - mov cr3, ebx - sysexit + mov eax, [temporaryESP] + mov esp, eax + pop ebp + ret diff --git a/src/kernel/util/list.c b/src/kernel/util/list.c index aa04956..a5f39fb 100644 --- a/src/kernel/util/list.c +++ b/src/kernel/util/list.c @@ -3,9 +3,17 @@ void listAdd(ListElement **list, void *data) { ListElement *element = malloc(sizeof(ListElement)); - element->next = *list; element->data = data; - *list = element; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; } void *listPopFirst(ListElement **list) { diff --git a/src/userland/loader/main.c b/src/userland/loader/main.c index 3a6f72e..271647b 100644 --- a/src/userland/loader/main.c +++ b/src/userland/loader/main.c @@ -1,45 +1,30 @@ #include #include -void syscall(void *callData) { - Syscall *call = callData; - call->respondingTo = 0; - call->resume = false; - asm("mov %%ebp, %%eax" : "=a"(call->esp)); - call->address = &&returnAddress; - asm("sysenter\n" ::"a"(callData)); -returnAddress: - asm("nop"); - return; +#define PTR(x) ((void *)(uintptr_t)x) +#define U32(x) ((uint32_t)(uintptr_t)x) + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp, result; + asm("push %%eax" ::"a"(&&end)); + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +end: + // eax is set by the kernel as the return value + asm("nop" : "=a"(result)); + return result; } -void makeRequest(char *moduleName, char *functionName, void *data, - uint32_t size) { - RequestSyscall call = { - .function = SYS_REQUEST, - .serviceName = moduleName, - .providerName = functionName, - .data = data, - .dataSize = size, - }; - syscall(&call); +void request(uint32_t module, uint32_t function, void *data, uint32_t size) { + syscall(SYS_REQUEST, module, function, U32(data), size); } void installServiceProvider(char *name, void(provider)(void *)) { - RegisterServiceProviderSyscall call = { - .function = SYS_REGISTER_FUNCTION, - .name = name, - .handler = provider, - }; - syscall(&call); -} - -void loadFromInitrd(char *name) { - LoadFromInitrdSyscall call = { - .function = SYS_LOAD_INITRD, - .programName = name, - }; - syscall(&call); + syscall(SYS_REGISTER_FUNCTION, U32(name), U32(provider), 0, 0); } uint32_t strlen(char *string) { @@ -51,7 +36,23 @@ return size; } -void log(char *message) { makeRequest("log", "log", message, strlen(message)); } +uint32_t getModule(char *name) { + return syscall(SYS_GET_SERVICE, U32(name), strlen(name), 0, 0); +} + +uint32_t getProvider(uint32_t module, char *name) { + return syscall(SYS_GET_PROVIDER, module, U32(name), strlen(name), 0); +} + +void loadFromInitrd(char *name) { + syscall(SYS_LOAD_INITRD, U32(name), strlen(name), 0, 0); +} + +void log(char *message) { + uint32_t module = getModule("log"); + uint32_t provider = getProvider(module, "log"); + request(module, provider, message, strlen(message)); +} int32_t main() { loadFromInitrd("log"); diff --git a/src/include/syscalls.h b/src/include/syscalls.h index e52e178..2a35dd8 100644 --- a/src/include/syscalls.h +++ b/src/include/syscalls.h @@ -11,53 +11,20 @@ SYS_IO_IN = 3, SYS_IO_OUT = 4, SYS_LOAD_INITRD = 5, + SYS_GET_SERVICE = 6, + SYS_GET_PROVIDER = 7, } SyscallIds; typedef struct Syscall { uint32_t function; - void *address; + uint32_t parameters[4]; + uint32_t returnValue; void *esp; void *cr3; struct Syscall *respondingTo; void *service; bool resume; bool avoidReschedule; - struct Syscall *writeBack; } Syscall; -typedef struct { - Syscall; - void *handler; - char *name; -} RegisterServiceProviderSyscall; - -typedef struct { - Syscall; - char *serviceName; - char *providerName; - uint32_t dataSize; - void *data; -} RequestSyscall; - -typedef struct { - Syscall; - uint16_t port; - uint8_t size; -} IOPortSyscall; - -typedef struct { - IOPortSyscall; - uint32_t result; -} IOPortInSyscall; - -typedef struct { - IOPortSyscall; - uint32_t value; -} IOPortOutSyscall; - -typedef struct { - Syscall; - char *programName; -} LoadFromInitrdSyscall; - #endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 49ac65c..a70cf75 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -22,20 +22,17 @@ Provider *provider = findProvider(service, "main"); Syscall *runTask = malloc(sizeof(Syscall)); runTask->function = SYS_RUN; - runTask->address = provider->address; runTask->resume = true; runTask->cr3 = getPhysicalAddressKernel(service->pagingInfo.pageDirectory); runTask->esp = malloc(0x1000); runTask->respondingTo = respondingTo; runTask->service = service; memset(runTask->esp, 0, 0x1000); - runTask->esp += 0xFFC; - *(void **)runTask->esp = &runEnd; + runTask->esp += 0xFF8; + *(void **)runTask->esp = provider->address; + *(void **)(runTask->esp + 4) = &runEnd; sharePage(&service->pagingInfo, runTask->esp, runTask->esp); listAdd(&callsToProcess, runTask); - if (!runTask->address) { - asm("hlt" ::"a"(runTask), "b"(provider), "c"(service), "d"(elfData)); - } return runTask; } @@ -68,8 +65,6 @@ call->resume = true; if (!call->avoidReschedule) { listAdd(&callsToProcess, call); - void *temporary = mapTemporary(call->writeBack); - memcpy(call, temporary, sizeof(IOPortInSyscall)); } } } diff --git a/src/kernel/memory/malloc.c b/src/kernel/memory/malloc.c index e715905..c6aa5f9 100644 --- a/src/kernel/memory/malloc.c +++ b/src/kernel/memory/malloc.c @@ -15,7 +15,9 @@ block->allocatedCoarse &= ~(1 << coarse); break; } - return ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + void *result = ((uint8_t *)block) + block->blockSize * (32 * coarse + fine); + memset(result, 0, block->blockSize); + return result; } void *malloc(uint32_t size) { diff --git a/src/kernel/service/service.asm b/src/kernel/service/service.asm index f538328..9c47365 100644 --- a/src/kernel/service/service.asm +++ b/src/kernel/service/service.asm @@ -2,7 +2,7 @@ global runFunction global runEnd -global runEndSyscall +global temporaryESP extern currentSyscall @@ -13,17 +13,17 @@ mov eax, esp mov [temporaryESP], eax mov ebx, [currentSyscall] - mov ecx, [ebx + 8] + mov ecx, [ebx + 24] mov ebp, ecx - mov edx, [ebx + 4] - mov eax, [ebx + 12] + mov edx, returnPoint + mov eax, [ebx + 28] + mov ebx, [ebx + 20] mov cr3, eax + mov eax, ebx sysexit runEnd: mov eax, 0 sysenter -runEndSyscall: - mov eax, [temporaryESP] - mov esp, eax - pop ebp + +returnPoint: ret diff --git a/src/kernel/service/services.c b/src/kernel/service/services.c index 450b4b2..a61ff1d 100644 --- a/src/kernel/service/services.c +++ b/src/kernel/service/services.c @@ -13,9 +13,6 @@ void resume(Syscall *syscall) { currentSyscall = syscall; - if (!syscall->address) { - asm("hlt" ::"a"(syscall)); - } runFunction(); } diff --git a/src/kernel/syscalls/syscall.c b/src/kernel/syscalls/syscall.c index 51dd4c4..541cea0 100644 --- a/src/kernel/syscalls/syscall.c +++ b/src/kernel/syscalls/syscall.c @@ -5,7 +5,6 @@ #include #include -extern void *runEndSyscall; extern ListElement *callsToProcess; extern void(syscallStub)(); extern Syscall *currentSyscall; @@ -19,30 +18,30 @@ 0); // when transitioning to 64 bit: U32(value) >> 32); } -void handleSyscall(void *cr3, Syscall *callData) { - if (!callData) { +void handleSyscall(void *esp, uint32_t function, uint32_t parameter0, + uint32_t parameter1, uint32_t parameter2, + uint32_t parameter3) { + if (!function) { if (currentSyscall->respondingTo) { listAdd(&callsToProcess, currentSyscall->respondingTo); } - asm("jmp runEndSyscall"); + return; } - Service *service = currentSyscall->service; - void *dataPhysical = - getPhysicalAddress(service->pagingInfo.pageDirectory, callData); - Syscall *call = malloc(sizeof(RequestSyscall)); - void *data = mapTemporary(dataPhysical); - memcpy(data, call, sizeof(RequestSyscall)); - call->cr3 = cr3; + Syscall *call = malloc(sizeof(Syscall)); + call->function = function; + call->parameters[0] = parameter0; + call->parameters[1] = parameter1; + call->parameters[2] = parameter2; + call->parameters[3] = parameter3; call->service = currentSyscall->service; - call->writeBack = dataPhysical; + call->esp = esp; if (!call->respondingTo) { call->respondingTo = currentSyscall->respondingTo; } - if (!call->address) { - asm("hlt" ::"a"(call), "b"(dataPhysical)); - } + Service *currentService = currentSyscall->service; + call->cr3 = + getPhysicalAddressKernel(currentService->pagingInfo.pageDirectory); listAdd(&callsToProcess, call); - asm("jmp runEndSyscall"); } void *syscallStubPtr = syscallStub; @@ -53,28 +52,33 @@ writeMsrRegister(0x176, syscallStubPtr); // the handler } -void handleInstallSyscall(RegisterServiceProviderSyscall *call) { +void handleInstallSyscall(Syscall *call) { Provider *provider = malloc(sizeof(Provider)); Service *service = call->service; - char *providerName = kernelMapPhysical( - getPhysicalAddress(service->pagingInfo.pageDirectory, call->name)); + char *providerName = kernelMapPhysical(getPhysicalAddress( + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); provider->name = providerName; - provider->address = call->handler; + provider->address = PTR(call->parameters[1]); provider->service = call->service; listAdd(&service->providers, provider); } -void handleRequestSyscall(RequestSyscall *call) { +void *listGet(ListElement *list, uint32_t position) { + for (uint32_t i = 0; i < position; i++) { + list = list->next; + } + return list->data; +} + +extern ListElement *services; + +void handleRequestSyscall(Syscall *call) { Service *service = call->service; - char *serviceName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->serviceName)); - Service *providerService = findService(serviceName); - char *providerName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->providerName)); - Provider *callProvider = findProvider(providerService, providerName); + Service *providerService = listGet(services, call->parameters[0]); + Provider *provider = + listGet(providerService->providers, call->parameters[1]); Syscall *runCall = malloc(sizeof(Syscall)); runCall->function = SYS_RUN; - runCall->address = callProvider->address; runCall->esp = malloc(0x1000); runCall->respondingTo = (void *)call; runCall->cr3 = @@ -82,50 +86,94 @@ runCall->service = providerService; runCall->resume = true; sharePage(&providerService->pagingInfo, runCall->esp, runCall->esp); - runCall->esp += 0xFFC; - *(void **)runCall->esp = &runEnd; + runCall->esp += 0xFF8; + *(void **)runCall->esp = provider->address; + *(void **)(runCall->esp + 4) = &runEnd; listAdd(&callsToProcess, runCall); call->avoidReschedule = true; } -void handleIOInSyscall(IOPortInSyscall *call) { - switch (call->size) { +void handleIOInSyscall(Syscall *call) { + switch (call->parameters[0]) { case 1: - asm("in %%dx, %%al" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%al" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; case 2: - asm("in %%dx, %%ax" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%ax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; case 4: - asm("in %%dx, %%eax" : "=a"(call->result) : "d"(call->port)); + asm("in %%dx, %%eax" + : "=a"(call->returnValue) + : "d"(call->parameters[1])); break; } } -void handleIOOutSyscall(IOPortOutSyscall *call) { - switch (call->size) { +void handleIOOutSyscall(Syscall *call) { + switch (call->parameters[0]) { case 1: - asm("out %0, %1" : : "a"((uint8_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint8_t)call->parameters[2]), "Nd"(call->parameters[1])); break; case 2: - asm("out %0, %1" : : "a"((uint16_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint16_t)call->parameters[2]), "Nd"(call->parameters[1])); break; case 4: - asm("out %0, %1" : : "a"((uint32_t)call->value), "Nd"(call->port)); + asm("out %0, %1" + : + : "a"((uint32_t)call->parameters[2]), "Nd"(call->parameters[1])); break; } } extern Syscall *loadInitrdProgram(char *name, Syscall *respondingTo); -void handleLoadFromInitrdSyscall(LoadFromInitrdSyscall *call) { +void handleLoadFromInitrdSyscall(Syscall *call) { Service *service = call->service; char *programName = kernelMapPhysical(getPhysicalAddress( - service->pagingInfo.pageDirectory, call->programName)); + service->pagingInfo.pageDirectory, PTR(call->parameters[0]))); loadInitrdProgram(programName, (void *)call); call->avoidReschedule = true; } +void handleGetServiceSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[0]))); + foreach (services, Service *, service, { + if (stringEquals(service->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + +void handleGetProviderSyscall(Syscall *call) { + uint32_t i = 0; + Service *callService = call->service; + char *name = kernelMapPhysical(getPhysicalAddress( + callService->pagingInfo.pageDirectory, PTR(call->parameters[1]))); + Service *providerService = listGet(services, call->parameters[0]); + foreach (providerService->providers, Provider *, provider, { + if (stringEquals(provider->name, name)) { + call->returnValue = i; + return; + } + i++; + }) + ; +} + void (*syscallHandlers[])(Syscall *) = { 0, (void *)handleInstallSyscall, @@ -133,4 +181,6 @@ (void *)handleIOInSyscall, (void *)handleIOOutSyscall, (void *)handleLoadFromInitrdSyscall, + (void *)handleGetServiceSyscall, + (void *)handleGetProviderSyscall, }; diff --git a/src/kernel/syscalls/syscallStub.asm b/src/kernel/syscalls/syscallStub.asm index ad29d6e..f8213a8 100644 --- a/src/kernel/syscalls/syscallStub.asm +++ b/src/kernel/syscalls/syscallStub.asm @@ -3,16 +3,23 @@ global syscallStub extern handleSyscall +extern temporaryESP + +temporaryEAX: resb 4 syscallStub: - mov ebx, cr3 - mov ecx, 0x500000 - mov cr3, ecx - push eax + mov [temporaryEAX], eax + mov eax, 0x500000 + mov cr3, eax + mov eax, [temporaryEAX] + push esi + push edx + push ecx push ebx + push eax + push edi call handleSyscall - pop ebx - mov edx, [eax+4] - mov ecx, [eax+8] - mov cr3, ebx - sysexit + mov eax, [temporaryESP] + mov esp, eax + pop ebp + ret diff --git a/src/kernel/util/list.c b/src/kernel/util/list.c index aa04956..a5f39fb 100644 --- a/src/kernel/util/list.c +++ b/src/kernel/util/list.c @@ -3,9 +3,17 @@ void listAdd(ListElement **list, void *data) { ListElement *element = malloc(sizeof(ListElement)); - element->next = *list; element->data = data; - *list = element; + element->next = NULL; + if (!*list) { + *list = element; + return; + } + ListElement *current = *list; + while (current->next) { + current = current->next; + } + current->next = element; } void *listPopFirst(ListElement **list) { diff --git a/src/userland/loader/main.c b/src/userland/loader/main.c index 3a6f72e..271647b 100644 --- a/src/userland/loader/main.c +++ b/src/userland/loader/main.c @@ -1,45 +1,30 @@ #include #include -void syscall(void *callData) { - Syscall *call = callData; - call->respondingTo = 0; - call->resume = false; - asm("mov %%ebp, %%eax" : "=a"(call->esp)); - call->address = &&returnAddress; - asm("sysenter\n" ::"a"(callData)); -returnAddress: - asm("nop"); - return; +#define PTR(x) ((void *)(uintptr_t)x) +#define U32(x) ((uint32_t)(uintptr_t)x) + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp, result; + asm("push %%eax" ::"a"(&&end)); + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +end: + // eax is set by the kernel as the return value + asm("nop" : "=a"(result)); + return result; } -void makeRequest(char *moduleName, char *functionName, void *data, - uint32_t size) { - RequestSyscall call = { - .function = SYS_REQUEST, - .serviceName = moduleName, - .providerName = functionName, - .data = data, - .dataSize = size, - }; - syscall(&call); +void request(uint32_t module, uint32_t function, void *data, uint32_t size) { + syscall(SYS_REQUEST, module, function, U32(data), size); } void installServiceProvider(char *name, void(provider)(void *)) { - RegisterServiceProviderSyscall call = { - .function = SYS_REGISTER_FUNCTION, - .name = name, - .handler = provider, - }; - syscall(&call); -} - -void loadFromInitrd(char *name) { - LoadFromInitrdSyscall call = { - .function = SYS_LOAD_INITRD, - .programName = name, - }; - syscall(&call); + syscall(SYS_REGISTER_FUNCTION, U32(name), U32(provider), 0, 0); } uint32_t strlen(char *string) { @@ -51,7 +36,23 @@ return size; } -void log(char *message) { makeRequest("log", "log", message, strlen(message)); } +uint32_t getModule(char *name) { + return syscall(SYS_GET_SERVICE, U32(name), strlen(name), 0, 0); +} + +uint32_t getProvider(uint32_t module, char *name) { + return syscall(SYS_GET_PROVIDER, module, U32(name), strlen(name), 0); +} + +void loadFromInitrd(char *name) { + syscall(SYS_LOAD_INITRD, U32(name), strlen(name), 0, 0); +} + +void log(char *message) { + uint32_t module = getModule("log"); + uint32_t provider = getProvider(module, "log"); + request(module, provider, message, strlen(message)); +} int32_t main() { loadFromInitrd("log"); diff --git a/src/userland/log/main.c b/src/userland/log/main.c index 46827ae..e2a95b1 100644 --- a/src/userland/log/main.c +++ b/src/userland/log/main.c @@ -1,36 +1,43 @@ #include #include -void syscall(void *callData) { - Syscall *call = callData; - call->respondingTo = 0; - call->resume = false; - asm("mov %%ebp, %%eax" : "=a"(call->esp)); - call->address = &&returnAddress; - asm("sysenter\n" ::"a"(callData)); -returnAddress: - asm("nop"); - return; +#define PTR(x) ((void *)(uintptr_t)x) +#define U32(x) ((uint32_t)(uintptr_t)x) + +uint32_t syscall(uint32_t function, uint32_t parameter0, uint32_t parameter1, + uint32_t parameter2, uint32_t parameter3) { + uint32_t esp, result; + asm("push %%eax" ::"a"(&&end)); + asm("mov %%esp, %%eax" : "=a"(esp)); + asm("sysenter\n" + : + : "a"(function), "b"(parameter0), "c"(parameter1), "d"(parameter2), + "S"(parameter3), "D"(esp)); +// eax is set by the kernel as the return value +end: + asm("nop" : "=a"(result)); + return result; +} + +void installServiceProvider(char *name, void(provider)(void *)) { + syscall(SYS_REGISTER_FUNCTION, U32(name), U32(provider), 0, 0); +} + +uint32_t strlen(char *string) { + uint32_t size = 0; + while (*string) { + string++; + size++; + } + return size; } uint32_t ioIn(uint16_t port, uint8_t size) { - IOPortInSyscall call = { - .function = SYS_IO_IN, - .port = port, - .size = size, - }; - syscall(&call); - return call.result; + return syscall(SYS_IO_IN, size, port, 0, 0); } void ioOut(uint16_t port, uint32_t value, uint8_t size) { - IOPortOutSyscall call = { - .function = SYS_IO_OUT, - .port = port, - .value = value, - .size = size, - }; - syscall(&call); + syscall(SYS_IO_OUT, size, port, value, 0); } void writeParallel(uint8_t data) { @@ -52,25 +59,6 @@ writeParallel('g'); } -void makeRequest(char *moduleName, char *functionName) { - RequestSyscall call = { - .function = SYS_REQUEST, - .serviceName = moduleName, - .providerName = functionName, - .data = 0, - }; - syscall(&call); -} - -void installServiceProvider(char *name, void(provider)(void *)) { - RegisterServiceProviderSyscall call = { - .function = SYS_REGISTER_FUNCTION, - .name = name, - .handler = provider, - }; - syscall(&call); -} - int32_t main() { installServiceProvider("log", log); writeParallel('m');