]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ia32/task-ia32-amd64.cpp
Some minor fixes.
[l4.git] / kernel / fiasco / src / kern / ia32 / task-ia32-amd64.cpp
1 IMPLEMENTATION [ia32 || amd64]:
2
3 #include "gdt.h"
4 #include "std_macros.h"
5 #include "x86desc.h"
6
7 PRIVATE inline NEEDS["gdt.h"]
8 bool
9 Task::invoke_arch(L4_msg_tag &tag, Utcb *utcb)
10 {
11   switch (utcb->values[0])
12     {
13     case Ldt_set_x86:
14         {
15           enum
16           {
17             Utcb_values_per_ldt_entry
18               = Cpu::Ldt_entry_size / sizeof(utcb->values[0]),
19           };
20           if (EXPECT_FALSE(tag.words() < 3
21                            || tag.words() % Utcb_values_per_ldt_entry))
22             {
23               tag = commit_result(-L4_err::EInval);
24               return true;
25             }
26
27           unsigned entry_number  = utcb->values[1];
28           unsigned size          = (tag.words() - 2) * sizeof(utcb->values[0]);
29
30           // Allocate the memory if not yet done
31           if (!_ldt.addr())
32             _ldt.alloc();
33
34           if (entry_number * Cpu::Ldt_entry_size + size > Config::PAGE_SIZE)
35             {
36               WARN("set_ldt: LDT size exceeds one page, not supported.");
37               tag = commit_result(-L4_err::EInval);
38               return true;
39             }
40
41           _ldt.size(size + Cpu::Ldt_entry_size * entry_number);
42
43           Address desc_addr = reinterpret_cast<Address>(&utcb->values[2]);
44           Gdt_entry desc;
45           Gdt_entry *ldtp
46             = reinterpret_cast<Gdt_entry *>(_ldt.addr()) + entry_number;
47
48           while (size >= Cpu::Ldt_entry_size)
49             {
50               desc = *reinterpret_cast<Gdt_entry const *>(desc_addr);
51               if (desc.unsafe())
52                 {
53                   WARN("set_ldt: Bad descriptor.");
54                   tag = commit_result(-L4_err::EInval);
55                   return true;
56                 }
57
58               *ldtp      = desc;
59               size      -= Cpu::Ldt_entry_size;
60               desc_addr += Cpu::Ldt_entry_size;
61               ldtp++;
62             }
63
64           if (this == current()->space())
65             Cpu::cpus.cpu(current_cpu()).enable_ldt(_ldt.addr(), _ldt.size());
66
67           tag = commit_result(0);
68         }
69       return true;
70     }
71
72
73
74
75   return false;
76 }