summaryrefslogtreecommitdiffstats
path: root/sys/message.c
blob: c4414e0b5e1df2902a5542e5745721ced0daf7b5 (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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "message.h"
#include "api/error.h"
#include "jove.h"
#include "hal/memory.h"
#include "hal/obj.h"
#include "lib/printf.h"

static inline uintptr_t
s_message_addr(jove_owned_obj_t *message_obj)
{
    return (obj_getvalue(message_obj) >> 1) << 12;
}

int message_new(jove_owned_obj_t *untyped_obj)
{
    uintmax_t untyped_value = obj_getvalue(untyped_obj);
    jove_untyped_t *untyped = obj_deref(untyped_obj);
    if(untyped->limit != 0x1000) {
        klogf("Passed untyped has bad size : %x vs %x\n", untyped->limit, MESSAGE_SIZE);
        return -EBADSIZE;
    }
    if(untyped_value & (MESSAGE_ALIGN - 1)) {
        klogf("Passed untyped has bad alignment : %x\n", untyped_value & (MESSAGE_ALIGN - 1));
        return -EALIGN;
    }

    obj_settype(untyped_obj, JOVE_OBJ_MESSAGE);
    obj_setvalue(untyped_obj, obj_getvalue(untyped_obj) >> 11);
    return 0;
}

inline int
message_hasmap(jove_owned_obj_t *message_obj)
{
    return obj_getvalue(message_obj) & 1;
}

virtaddr_t
message_unmap(jove_owned_obj_t *message_obj, jove_owned_obj_t *pagedir_obj)
{
    errno = 0;
    if(message_hasmap(message_obj) == 0) {
        klogf("Message %p doesn't have a map\n", obj_getvalue(message_obj));
        errno = -ENOMAP;
        return 0;
    }

    virtaddr_t message_vaddr = s_message_addr(message_obj);
    virtaddr_t *mapping = pagedir_get_mapping(pagedir_obj, message_vaddr);
    physaddr_t message_pfn = pagedir_mapping_get_pfn(mapping);

    pagedir_mapping_set_present(mapping, false);
    obj_setvalue(message_obj, message_pfn << 1);
    pagedir_invlpg(message_vaddr);
    message_klogf("Unmapped message %p from %p\n", message_pfn << 12, message_vaddr);

    return message_vaddr;
}

int
message_map(jove_owned_obj_t *message, jove_owned_obj_t *pagedir, virtaddr_t vaddr)
{
    if(message_hasmap(message)) {
        return -EHASMAP;
    }

    virtaddr_t message_paddr = s_message_addr(message);
    virtaddr_t *mapping = pagedir_get_mapping(pagedir, vaddr);

    if(pagedir_mapping_is_present(mapping)) {
        klogf("Mapping %p is occupied\n",
                mapping, message);
        return -EHASMAP;
    }

    pagedir_mapping_set_pfn(mapping, message_paddr >> 12);
    pagedir_mapping_set_present(mapping, true);
    pagedir_mapping_set_writeable(mapping, true);
    pagedir_mapping_set_user(mapping, true);
    pagedir_mapping_set_type(mapping, JOVE_MAPPING_TYPE_MESSAGE);

    pagedir_invlpg(vaddr);

    message_klogf("Mapped message %p to %p\n", message_paddr, vaddr);
    obj_setvalue(message, (vaddr >> 11) | 1);
    return 0;
}

virtaddr_t message_getdata(jove_owned_obj_t *message)
{
    uintptr_t message_addr = s_message_addr(message);
    if(message_hasmap(message)) return message_addr;
    return (virtaddr_t)phys_tovirt(message_addr);
}