mirror of
https://github.com/drasko/codezero.git
synced 2026-01-14 20:03:16 +01:00
utcb as a shared page instead of the message registers. Implemented the code that passes task information from mm0 to fs0 using the fs0 utcb. The code seems to work OK but: There's an issue with anon pages that they end up on the same swapfile and with same file offsets (e.g. utcb and stack at offset 0). Need to fix this issue but otherwise this implementation seems to work. TODO: - Separate anon regions into separate vmfiles. - Possibly map the stacks from virtual files so that they can be read from userspace in the future for debugging. - Possibly utcb could be created as a shared memory object using shmget/shmat during startup.
159 lines
3.5 KiB
C
159 lines
3.5 KiB
C
/*
|
|
* FS0 task data initialisation.
|
|
*
|
|
* Copyright (C) 2008 Bahadir Balban
|
|
*/
|
|
#include <l4/macros.h>
|
|
#include <l4/lib/list.h>
|
|
#include <l4/api/errno.h>
|
|
#include <l4lib/arch/syscalls.h>
|
|
#include <l4lib/arch/syslib.h>
|
|
#include <l4lib/ipcdefs.h>
|
|
#include <lib/malloc.h>
|
|
#include <task.h>
|
|
#include <vfs.h>
|
|
|
|
|
|
struct tcb_head {
|
|
struct list_head list;
|
|
int total; /* Total threads */
|
|
} tcb_head;
|
|
|
|
struct tcb *find_task(int tid)
|
|
{
|
|
struct tcb *t;
|
|
|
|
list_for_each_entry(t, &tcb_head.list, list)
|
|
if (t->tid == tid)
|
|
return t;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Asks pager to send information about currently running tasks. Since this is
|
|
* called during initialisation, there can't be that many, so we assume message
|
|
* registers are sufficient. First argument tells how many there are, the rest
|
|
* tells the tids.
|
|
*/
|
|
int receive_pager_taskdata_orig(l4id_t *tdata)
|
|
{
|
|
int err;
|
|
|
|
/* Make the actual ipc call */
|
|
if ((err = l4_sendrecv(PAGER_TID, PAGER_TID,
|
|
L4_IPC_TAG_TASKDATA)) < 0) {
|
|
printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err);
|
|
return err;
|
|
}
|
|
|
|
/* Check if call itself was successful */
|
|
if ((err = l4_get_retval()) < 0) {
|
|
printf("%s: Error: %d.\n", __FUNCTION__, err);
|
|
return err;
|
|
}
|
|
|
|
/* Read total number of tasks. Note already used one mr. */
|
|
if ((tdata[0] = (l4id_t)read_mr(L4SYS_ARG0)) >= MR_UNUSED_TOTAL) {
|
|
printf("%s: Error: Too many tasks to read. Won't fit in mrs.\n",
|
|
__FUNCTION__);
|
|
BUG();
|
|
}
|
|
// printf("%s: %d Total tasks.\n", __FUNCTION__, tdata[0]);
|
|
|
|
/* Now read task ids. */
|
|
for (int i = 0; i < (int)tdata[0]; i++) {
|
|
tdata[1 + i] = (l4id_t)read_mr(L4SYS_ARG1 + i);
|
|
// printf("%s: Task id: %d\n", __FUNCTION__, tdata[1 + i]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct task_data {
|
|
unsigned long tid;
|
|
unsigned long utcb_address;
|
|
};
|
|
|
|
struct task_data_head {
|
|
unsigned long total;
|
|
struct task_data tdata[];
|
|
};
|
|
|
|
/* Read task information into the utcb buffer, since it wont fit into mrs. */
|
|
struct task_data_head *receive_pager_taskdata(void)
|
|
{
|
|
int err;
|
|
|
|
/* Ask pager to write the data at this address */
|
|
write_mr(L4SYS_ARG0, (unsigned long)utcb->buf);
|
|
|
|
/* Make the actual ipc call */
|
|
if ((err = l4_sendrecv(PAGER_TID, PAGER_TID,
|
|
L4_IPC_TAG_TASKDATA)) < 0) {
|
|
printf("%s: L4 IPC Error: %d.\n", __FUNCTION__, err);
|
|
return PTR_ERR(err);
|
|
}
|
|
|
|
/* Check if call itself was successful */
|
|
if ((err = l4_get_retval()) < 0) {
|
|
printf("%s: Error: %d.\n", __FUNCTION__, err);
|
|
return PTR_ERR(err);
|
|
}
|
|
|
|
printf("%s: %d Total tasks.\n", __FUNCTION__,
|
|
((struct task_data_head *)utcb->buf)->total);
|
|
|
|
return (struct task_data_head *)utcb->buf;
|
|
}
|
|
|
|
/* Allocate a task struct and initialise it */
|
|
struct tcb *create_tcb(void)
|
|
{
|
|
struct tcb *t;
|
|
|
|
if (!(t = kmalloc(sizeof(*t))))
|
|
return PTR_ERR(-ENOMEM);
|
|
|
|
INIT_LIST_HEAD(&t->list);
|
|
list_add_tail(&t->list, &tcb_head.list);
|
|
tcb_head.total++;
|
|
|
|
return t;
|
|
}
|
|
|
|
int init_task_structs(struct task_data_head *tdata_head)
|
|
{
|
|
struct tcb *t;
|
|
|
|
for (int i = 0; i < tdata_head->total; i++) {
|
|
if (IS_ERR(t = create_tcb()))
|
|
return (int)t;
|
|
|
|
/* Initialise fields sent by pager */
|
|
t->tid = tdata_head->tdata[i].tid;
|
|
t->utcb_address = tdata_head->tdata[i].utcb_address;
|
|
|
|
/* Initialise vfs specific fields. */
|
|
t->rootdir = vfs_root.pivot;
|
|
t->curdir = vfs_root.pivot;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int init_task_data(void)
|
|
{
|
|
struct task_data_head *tdata_head;
|
|
|
|
INIT_LIST_HEAD(&tcb_head.list);
|
|
|
|
/* Read how many tasks and tids of each */
|
|
BUG_ON((tdata_head = receive_pager_taskdata()) < 0);
|
|
|
|
/* Initialise local task structs using this info */
|
|
BUG_ON(init_task_structs(tdata_head) < 0);
|
|
|
|
return 0;
|
|
}
|
|
|