summaryrefslogtreecommitdiffstats
path: root/sys/syscall_region.c
blob: dc81634d7714fc506ea0994d324e9658e1d8fe48 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "api/error.h"
#include "api/syscall.h"
#include "hal/memory.h"
#include "lib/printf.h"
#include "jove.h"
#include "syscall.h"

static int
s_syscall_region_alloc(jove_owned_obj_t *region_obj,
                       jove_obj_t *objdir_obj,
                       lockstack_t *lockstack,
                       size_t bytes_left,
                       void *payload_data)
{
    size_t bytes_needed = sizeof(struct syscall_region_alloc);
    CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload");

    struct syscall_region_alloc *payload = payload_data;
    bytes_needed += payload->dest_pathlen * sizeof(objpath_part_t);

    CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for subject path");

    jove_perm_obj_t subject = link_traverse_objdir(objdir_obj, payload->dest_pathlen, payload->dest_path);
    lockstack_push(lockstack, subject.obj);

    CHECK_OBJEXISTS(subject.obj, "Destination path is bad.");
    CHECK_OBJPERM(subject, SYSCALL_PERM_REGION_ALLOC_TGT, "Destination path does not have correct permissions.");
    CHECK_OBJTYPE(subject.obj, JOVE_OBJ_NONE, "Destination object is not JOVE_OBJ_NONE");

    int sysret = 0;
    if(payload->alloc_pages == 1) {
        sysret = region_alloc(region_obj, subject.obj);
    }else{
        sysret = region_alloc_contig(region_obj, subject.obj, payload->alloc_pages);
    }
    if(sysret < 0) {
        klogf("Region alloc failed with reason: %s\n", errstr(-sysret));
    }
    return sysret;
}

int 
_syscall_handle_region(syscall_context_t *ctx)
{
    switch(ctx->header->callid) {
        case SYSCALL_REGION_ADDRESS:
            if(ctx->target.permissions & SYSCALL_PERM_REGION_GETTERS)
                return region_base(ctx->target.obj);
            return -EPERM;

        case SYSCALL_REGION_TOTAL_PAGES:
            if(ctx->target.permissions & SYSCALL_PERM_REGION_GETTERS)
                return region_pages(ctx->target.obj);
            return -EPERM;

        case SYSCALL_REGION_FREE_PAGES:
            if(ctx->target.permissions & SYSCALL_PERM_REGION_GETTERS)
                return region_freepages(ctx->target.obj);
            return -EPERM;

        case SYSCALL_REGION_ALLOC:
            if(ctx->target.permissions & SYSCALL_PERM_REGION_ALLOC)
                return s_syscall_region_alloc(ctx->target.obj, ctx->objdir, &ctx->lockstack, ctx->bytes_left, ctx->payload);
            return -EPERM;

        default:
            return -EBADCALL;
    }
}