mirror of
https://github.com/drasko/codezero.git
synced 2026-01-28 10:43:14 +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 init_ktcb_list(void);
|
||||||
void task_update_utcb(struct ktcb *cur, struct ktcb *next);
|
void task_update_utcb(struct ktcb *cur, struct ktcb *next);
|
||||||
|
int tcb_check_and_lazy_map_utcb(struct ktcb *task);
|
||||||
|
|
||||||
#endif /* __TCB_H__ */
|
#endif /* __TCB_H__ */
|
||||||
|
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ int check_mapping(unsigned long vaddr, unsigned long size,
|
|||||||
void copy_pgd_kern_all(pgd_table_t *);
|
void copy_pgd_kern_all(pgd_table_t *);
|
||||||
pte_t virt_to_pte(unsigned long virtual);
|
pte_t virt_to_pte(unsigned long virtual);
|
||||||
pte_t virt_to_pte_from_pgd(unsigned long virtual, pgd_table_t *pgd);
|
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__ */
|
#endif /* __GLUE_ARM_MEMORY_H__ */
|
||||||
|
|
||||||
|
|||||||
@@ -40,11 +40,9 @@ int ipc_full_copy(struct ktcb *to, struct ktcb *from)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Check that utcb memory accesses won't fault us */
|
/* Check that utcb memory accesses won't fault us */
|
||||||
if ((ret = check_access(to->utcb_address, UTCB_SIZE,
|
if ((ret = tcb_check_and_lazy_map_utcb(to)) < 0)
|
||||||
MAP_SVC_RW_FLAGS, 0)) < 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = check_access(to->utcb_address, UTCB_SIZE,
|
if ((ret = tcb_check_and_lazy_map_utcb(from)) < 0)
|
||||||
MAP_SVC_RW_FLAGS, 0)) < 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Directly copy from one utcb to another */
|
/* 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)));
|
BUG_ON(!(flags = space_flags_to_ptflags(flags)));
|
||||||
|
|
||||||
for (int i = 0; i < npages; i++) {
|
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 */
|
/* Check if pte perms are equal or gt given flags */
|
||||||
if ((pte & PTE_PROT_MASK) >= (flags & PTE_PROT_MASK))
|
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;
|
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,
|
int check_mapping(unsigned long vaddr, unsigned long size,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <l4/generic/space.h>
|
#include <l4/generic/space.h>
|
||||||
#include <l4/lib/idpool.h>
|
#include <l4/lib/idpool.h>
|
||||||
#include <l4/api/kip.h>
|
#include <l4/api/kip.h>
|
||||||
|
#include <l4/api/errno.h>
|
||||||
#include INC_ARCH(exception.h)
|
#include INC_ARCH(exception.h)
|
||||||
#include INC_SUBARCH(mm.h)
|
#include INC_SUBARCH(mm.h)
|
||||||
#include INC_GLUE(memory.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;
|
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