mirror of
https://github.com/drasko/codezero.git
synced 2026-01-12 02:43:15 +01:00
Full utcb copying partially works now.
This commit is contained in:
@@ -145,6 +145,7 @@ void tcb_delete(struct ktcb *tcb);
|
||||
|
||||
void init_ktcb_list(void);
|
||||
void task_update_utcb(struct ktcb *cur, struct ktcb *next);
|
||||
int tcb_check_and_lazy_map_utcb(struct ktcb *task);
|
||||
|
||||
#endif /* __TCB_H__ */
|
||||
|
||||
|
||||
@@ -130,6 +130,7 @@ int check_mapping(unsigned long vaddr, unsigned long size,
|
||||
void copy_pgd_kern_all(pgd_table_t *);
|
||||
pte_t virt_to_pte(unsigned long virtual);
|
||||
pte_t virt_to_pte_from_pgd(unsigned long virtual, pgd_table_t *pgd);
|
||||
unsigned long virt_to_phys_by_pgd(unsigned long vaddr, pgd_table_t *pgd);
|
||||
|
||||
#endif /* __GLUE_ARM_MEMORY_H__ */
|
||||
|
||||
|
||||
@@ -40,11 +40,9 @@ int ipc_full_copy(struct ktcb *to, struct ktcb *from)
|
||||
int ret;
|
||||
|
||||
/* Check that utcb memory accesses won't fault us */
|
||||
if ((ret = check_access(to->utcb_address, UTCB_SIZE,
|
||||
MAP_SVC_RW_FLAGS, 0)) < 0)
|
||||
if ((ret = tcb_check_and_lazy_map_utcb(to)) < 0)
|
||||
return ret;
|
||||
if ((ret = check_access(to->utcb_address, UTCB_SIZE,
|
||||
MAP_SVC_RW_FLAGS, 0)) < 0)
|
||||
if ((ret = tcb_check_and_lazy_map_utcb(from)) < 0)
|
||||
return ret;
|
||||
|
||||
/* Directly copy from one utcb to another */
|
||||
|
||||
@@ -256,7 +256,7 @@ int check_mapping_pgd(unsigned long vaddr, unsigned long size,
|
||||
BUG_ON(!(flags = space_flags_to_ptflags(flags)));
|
||||
|
||||
for (int i = 0; i < npages; i++) {
|
||||
pte = virt_to_pte(vaddr + i * PAGE_SIZE);
|
||||
pte = virt_to_pte_from_pgd(vaddr + i * PAGE_SIZE, pgd);
|
||||
|
||||
/* Check if pte perms are equal or gt given flags */
|
||||
if ((pte & PTE_PROT_MASK) >= (flags & PTE_PROT_MASK))
|
||||
@@ -268,6 +268,11 @@ int check_mapping_pgd(unsigned long vaddr, unsigned long size,
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long virt_to_phys_by_pgd(unsigned long vaddr, pgd_table_t *pgd)
|
||||
{
|
||||
pte_t pte = virt_to_pte_from_pgd(vaddr, pgd);
|
||||
return pte & ~PAGE_MASK;
|
||||
}
|
||||
|
||||
int check_mapping(unsigned long vaddr, unsigned long size,
|
||||
unsigned int flags)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <l4/generic/space.h>
|
||||
#include <l4/lib/idpool.h>
|
||||
#include <l4/api/kip.h>
|
||||
#include <l4/api/errno.h>
|
||||
#include INC_ARCH(exception.h)
|
||||
#include INC_SUBARCH(mm.h)
|
||||
#include INC_GLUE(memory.h)
|
||||
@@ -164,3 +165,41 @@ void task_update_utcb(struct ktcb *cur, struct ktcb *next)
|
||||
kip.utcb = next->utcb_address;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether a task's utcb is currently accessible by the kernel
|
||||
* It returns an error if its not paged in yet, and also maps a non-current
|
||||
* task's utcb to current task with kernel-access privileges.
|
||||
*/
|
||||
int tcb_check_and_lazy_map_utcb(struct ktcb *task)
|
||||
{
|
||||
unsigned int phys;
|
||||
int ret;
|
||||
|
||||
BUG_ON(!task->utcb_address);
|
||||
|
||||
if ((ret = check_access(task->utcb_address, UTCB_SIZE,
|
||||
MAP_SVC_RW_FLAGS, 0)) < 0) {
|
||||
/* Current task simply hasn't mapped its utcb */
|
||||
if (task == current) {
|
||||
return -EFAULT;
|
||||
} else {
|
||||
if (!(phys = virt_to_phys_by_pgd(task->utcb_address,
|
||||
TASK_PGD(task)))) {
|
||||
/* Task hasn't mapped its utcb */
|
||||
return -EFAULT;
|
||||
} else {
|
||||
/*
|
||||
* Task has utcb but it hasn't yet been mapped
|
||||
* to current task with kernel access. Do it.
|
||||
*/
|
||||
add_mapping_pgd(phys, task->utcb_address,
|
||||
page_align_up(UTCB_SIZE),
|
||||
MAP_SVC_RW_FLAGS,
|
||||
TASK_PGD(current));
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user