mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 10:53:16 +01:00
Removed bits from kernel where pager utcb is set.
Pagers now set their own utcb explicitly via exchange_registers. exregs accepts calls from active pagers for this purpose only.
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
#include <l4/generic/resource.h>
|
||||
#include <l4/generic/tcb.h>
|
||||
#include <l4/generic/space.h>
|
||||
#include <l4/generic/capability.h>
|
||||
#include <l4/generic/container.h>
|
||||
#include <l4/api/space.h>
|
||||
#include <l4/api/ipc.h>
|
||||
#include <l4/api/kip.h>
|
||||
@@ -33,6 +35,8 @@ void do_exchange_registers(struct ktcb *task, struct exregs_data *exregs)
|
||||
{
|
||||
task_context_t *context = &task->context;
|
||||
|
||||
if (!exregs->valid_vect)
|
||||
goto flags;
|
||||
/*
|
||||
* NOTE:
|
||||
* We don't care if register values point at invalid addresses
|
||||
@@ -74,29 +78,48 @@ void do_exchange_registers(struct ktcb *task, struct exregs_data *exregs)
|
||||
if (exregs->valid_vect & FIELD_TO_BIT(exregs_context_t, pc))
|
||||
context->pc = exregs->context.pc;
|
||||
|
||||
flags:
|
||||
/* Set thread's pager if one is supplied */
|
||||
if (exregs->flags & EXREGS_SET_PAGER)
|
||||
task->pagerid = exregs->pagerid;
|
||||
|
||||
/* Set thread's utcb if supplied */
|
||||
if (exregs->flags & EXREGS_SET_UTCB)
|
||||
if (exregs->flags & EXREGS_SET_UTCB) {
|
||||
task->utcb_address = exregs->utcb_address;
|
||||
|
||||
/*
|
||||
* If task is the one currently runnable,
|
||||
* update kip utcb reference
|
||||
*/
|
||||
if (task == current)
|
||||
task_update_utcb(task);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* exchange_registers()
|
||||
*
|
||||
* This call is used by the pagers to set (and in the future read)
|
||||
* the register context of a thread. The thread's registers can be
|
||||
* set only when the thread is in user mode. A newly created thread
|
||||
* that is the copy of another thread (forked or cloned) will also
|
||||
* be given its user mode context on the first chance to execute so
|
||||
* such threads can also be modified by this call before execution.
|
||||
* the register context of a thread. The thread's registers that are
|
||||
* set by this call are loaded whenever the thread gets a chance to
|
||||
* run in user mode.
|
||||
*
|
||||
* It is ensured that whenever this call is made, the thread is
|
||||
* either already running in user mode, or has been suspended in
|
||||
* kernel mode, just before returning to user mode.
|
||||
*
|
||||
* A newly created thread that is the copy of another thread (forked
|
||||
* or cloned) will also be given its user mode context on the first
|
||||
* chance to execute so such threads can also be modified by this
|
||||
* call before execution.
|
||||
*
|
||||
* A thread executing in the kernel cannot be modified since this
|
||||
* would compromise the kernel. Also the thread must be in suspended
|
||||
* condition so that the scheduler does not execute it as we modify
|
||||
* its context.
|
||||
*
|
||||
* FIXME: Still looks like suspended threads in the kernel
|
||||
* need to be made immutable. see src/glue/arm/systable.c
|
||||
*/
|
||||
int sys_exchange_registers(struct exregs_data *exregs, l4id_t tid)
|
||||
{
|
||||
@@ -114,30 +137,27 @@ int sys_exchange_registers(struct exregs_data *exregs, l4id_t tid)
|
||||
if (!mutex_trylock(&task->thread_control_lock))
|
||||
return -EAGAIN;
|
||||
|
||||
/* Now check that the task is suspended */
|
||||
if (task->state != TASK_INACTIVE) {
|
||||
/*
|
||||
* Now check that the task is suspended.
|
||||
*
|
||||
* Only modification of non-register fields are
|
||||
* allowed on active tasks and those tasks must
|
||||
* be the pagers making the call on themselves.
|
||||
*/
|
||||
if (task->state != TASK_INACTIVE && exregs->valid_vect &&
|
||||
current != task && task->pager->tcb != current) {
|
||||
err = -EACTIVE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if 0
|
||||
A suspended thread implies it cannot do any harm
|
||||
even if it is in kernel mode.
|
||||
/*
|
||||
* The thread must be in user mode for its context
|
||||
* to be modified.
|
||||
* FIXME:
|
||||
* Capability Check.
|
||||
* Whose clist are we ought to check? Pager's or threads?
|
||||
* Need to check exregs capability
|
||||
* Need to check utcb capability if present.
|
||||
* if ((exregs->flags & EXREGS_SET_UTCB) &&
|
||||
*/
|
||||
if (!TASK_IN_USER(task)) {
|
||||
err = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check UTCB is in valid range */
|
||||
if (exregs->flags & EXREGS_SET_UTCB &&
|
||||
!(exregs->utcb_address >= UTCB_AREA_START &&
|
||||
exregs->utcb_address < UTCB_AREA_END))
|
||||
return -EINVAL;
|
||||
|
||||
/* Copy registers */
|
||||
do_exchange_registers(task, exregs);
|
||||
|
||||
@@ -61,10 +61,8 @@ struct capability *capability_find_by_rtype(struct cap_list *clist,
|
||||
{
|
||||
struct capability *cap;
|
||||
|
||||
list_foreach_struct(cap, &clist->caps, list) {
|
||||
list_foreach_struct(cap, &clist->caps, list)
|
||||
if ((cap->type & CAP_RTYPE_MASK) == rtype)
|
||||
return cap;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ int container_init(struct container *c)
|
||||
init_ktcb_list(&c->ktcb_list);
|
||||
init_mutex_queue_head(&c->mutex_queue_head);
|
||||
|
||||
/* Ini pager structs */
|
||||
/* Init pager structs */
|
||||
for (int i = 0; i < CONFIG_MAX_PAGERS_USED; i++)
|
||||
cap_list_init(&c->pager[i].cap_list);
|
||||
|
||||
@@ -48,23 +48,23 @@ void kcont_insert_container(struct container *c,
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: Remove completely. Need to be done in userspace.
|
||||
* This searches pager capabilities and if it has a virtual memory area
|
||||
* defined as a UTCB, uses the first entry as its utcb. If not, it is
|
||||
* not an error, perhaps another pager will map its utcb.
|
||||
*/
|
||||
void task_setup_utcb(struct ktcb *task, struct pager *pager)
|
||||
void pager_init_utcb(struct ktcb *task, struct pager *pager)
|
||||
{
|
||||
struct capability *cap;
|
||||
|
||||
/* Find a virtual memory capability with UTCB map permissions */
|
||||
list_foreach_struct(cap, &pager->cap_list.caps, list) {
|
||||
if (((cap->type & CAP_RTYPE_MASK) ==
|
||||
CAP_RTYPE_VIRTMEM) &&
|
||||
(cap->access & CAP_MAP_UTCB)) {
|
||||
/* Use first address slot as pager's utcb */
|
||||
task->utcb_address = __pfn_to_addr(cap->start);
|
||||
return;
|
||||
}
|
||||
if (cap_rtype(cap) == CAP_RTYPE_VIRTMEM &&
|
||||
cap->access & CAP_MAP_UTCB) {
|
||||
/* Use first address slot as pager's utcb */
|
||||
task->utcb_address = __pfn_to_addr(cap->start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +146,8 @@ int init_first_pager(struct pager *pager,
|
||||
|
||||
/* Initialize ktcb */
|
||||
task_init_registers(task, pager->start_vma);
|
||||
task_setup_utcb(task, pager);
|
||||
|
||||
pager_init_utcb(task, pager);
|
||||
|
||||
/* Allocate space structure */
|
||||
if (!(space = alloc_space()))
|
||||
@@ -215,7 +216,7 @@ int init_pager(struct pager *pager, struct container *cont)
|
||||
|
||||
task_init_registers(task, pager->start_vma);
|
||||
|
||||
task_setup_utcb(task, pager);
|
||||
pager_init_utcb(task, pager);
|
||||
|
||||
task->space = address_space_create(0);
|
||||
|
||||
|
||||
@@ -274,7 +274,7 @@ static inline void context_switch(struct ktcb *next)
|
||||
arch_hardware_flush(TASK_PGD(next));
|
||||
|
||||
/* Update utcb region for next task */
|
||||
task_update_utcb(cur, next);
|
||||
task_update_utcb(next);
|
||||
|
||||
/* Switch context */
|
||||
arch_switch(cur, next);
|
||||
|
||||
@@ -156,10 +156,10 @@ unsigned int syscall_regs_offset = offsetof(struct ktcb, syscall_regs);
|
||||
* space as its context is loaded. The utcb region is a function of
|
||||
* this mapping and its offset that is reached via the KIP UTCB pointer
|
||||
*/
|
||||
void task_update_utcb(struct ktcb *cur, struct ktcb *next)
|
||||
void task_update_utcb(struct ktcb *task)
|
||||
{
|
||||
/* Update the KIP pointer */
|
||||
kip.utcb = next->utcb_address;
|
||||
kip.utcb = task->utcb_address;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -188,9 +188,6 @@ void kip_init()
|
||||
/* KIP + 0xFF0 is pointer to UTCB segment start address */
|
||||
utcb_ref = (struct utcb **)((unsigned long)&kip + UTCB_KIP_OFFSET);
|
||||
|
||||
/* All thread utcbs are allocated starting from UTCB_AREA_START */
|
||||
*utcb_ref = (struct utcb *)UTCB_AREA_START;
|
||||
|
||||
add_boot_mapping(virt_to_phys(&kip), USER_KIP_PAGE, PAGE_SIZE,
|
||||
MAP_USR_RO_FLAGS);
|
||||
printk("%s: Kernel built on %s, %s\n", __KERNELNAME__,
|
||||
|
||||
Reference in New Issue
Block a user