Root/mips/arch.ccp

1#pypp 0
2// Iris: micro-kernel for a capability-based operating system.
3// mips/arch.ccp: Most mips-specific parts.
4// Copyright 2009 Bas Wijnen <wijnen@debian.org>
5//
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19#define ARCH
20#include "kernel.hh"
21
22void kThread_arch_init (kThread *thread):
23    thread->arch.at = 0
24    for unsigned i = 0; i < 2; ++i:
25        thread->arch.v[i] = 0
26    for unsigned i = 0; i < 4; ++i:
27        thread->arch.a[i] = 0
28    for unsigned i = 0; i < 10; ++i:
29        thread->arch.t[i] = 0
30    thread->arch.gp = 0
31    thread->arch.fp = 0
32    thread->arch.ra = 0
33    thread->arch.hi = 0
34    thread->arch.lo = 0
35
36void kPage_arch_init (kPage *page):
37    page->arch.prev_mapped = NULL
38    page->arch.next_mapped = NULL
39
40void kThread_arch_receive (kThread *thread, Iris::Num protected_data, Iris::Num *data):
41    thread->arch.a[0] = data[0].l
42    thread->arch.a[1] = data[0].h
43    thread->arch.a[2] = data[1].l
44    thread->arch.a[3] = data[1].h
45    thread->arch.t[0] = protected_data.l
46    thread->arch.t[1] = protected_data.h
47
48unsigned *kThread_arch_info (kThread *thread, unsigned num):
49    switch num:
50        case 1:
51            return &thread->arch.at
52        case 2:
53            return &thread->arch.v[0]
54        case 3:
55            return &thread->arch.v[1]
56        case 4:
57            return &thread->arch.a[0]
58        case 5:
59            return &thread->arch.a[1]
60        case 6:
61            return &thread->arch.a[2]
62        case 7:
63            return &thread->arch.a[3]
64        case 8:
65            return &thread->arch.t[0]
66        case 9:
67            return &thread->arch.t[1]
68        case 10:
69            return &thread->arch.t[2]
70        case 11:
71            return &thread->arch.t[3]
72        case 12:
73            return &thread->arch.t[4]
74        case 13:
75            return &thread->arch.t[5]
76        case 14:
77            return &thread->arch.t[6]
78        case 15:
79            return &thread->arch.t[7]
80        case 16:
81            return &thread->arch.s[0]
82        case 17:
83            return &thread->arch.s[1]
84        case 18:
85            return &thread->arch.s[2]
86        case 19:
87            return &thread->arch.s[3]
88        case 20:
89            return &thread->arch.s[4]
90        case 21:
91            return &thread->arch.s[5]
92        case 22:
93            return &thread->arch.s[6]
94        case 23:
95            return &thread->arch.s[7]
96        case 24:
97            return &thread->arch.t[8]
98        case 25:
99            return &thread->arch.t[9]
100        case 26:
101            return &thread->arch.gp
102        case 27:
103            return &thread->sp
104        case 28:
105            return &thread->arch.fp
106        case 29:
107            return &thread->arch.ra
108        default:
109            return NULL
110
111void kMemory_arch_init (kMemory *mem):
112    mem->arch.asid = 1
113    mem->arch.directory = NULL
114    mem->arch.shadow = NULL
115
116static void tlb_reset (kMemory *mem, unsigned address, unsigned value):
117    //kdebug_line ()
118    unsigned asid = mem->arch.asid
119    if asids[asid] != (unsigned)mem:
120        //kdebug ("not resetting tlb, because the asid is not in use.\n")
121        return
122    //kdebug ("resetting tlb for ")
123    //kdebug_num (address)
124    //kdebug ("\n")
125    cp0_set (CP0_ENTRY_HI, address | asid)
126    __asm__ volatile ("tlbp")
127    unsigned idx
128    cp0_get (CP0_INDEX, idx)
129    if !(idx & (1 << 31)):
130        __asm__ volatile ("tlbr")
131        if address & (1 << PAGE_BITS):
132            cp0_set (CP0_ENTRY_LO1, value)
133        else:
134            cp0_set (CP0_ENTRY_LO0, value)
135        __asm__ volatile ("tlbwi")
136        #if 0
137        kdebug ("tlb reset ")
138        unsigned hi, lo0, lo1
139        cp0_get (CP0_ENTRY_LO0, lo0)
140        cp0_get (CP0_ENTRY_LO1, lo1)
141        cp0_get (CP0_ENTRY_HI, hi)
142        kdebug_num (idx, 2)
143        kdebug ('|')
144        kdebug_num (lo0)
145        kdebug (":")
146        kdebug_num (lo1)
147        kdebug (" for ")
148        kdebug_num (hi)
149        kdebug ("\n")
150        #endif
151    cp0_set (CP0_ENTRY_HI, old_current->address_space->arch.asid)
152
153static unsigned make_entry_lo (kPage *page):
154    //kdebug_line ()
155    if !page->frame:
156        //kdebug ("not mapping because there is no frame\n")
157        return 0
158    unsigned flags
159    if page->flags & Iris::Page::UNCACHED:
160        flags = 0x10 | 0x2
161    else:
162        // 18 is write-back cache; 00 is write-through cache.
163        flags = 0x18 | 0x2
164    if ~page->flags & Iris::Page::MAPPED_READONLY:
165        flags |= 0x4
166    return ((page->frame & ~0x80000000) >> 6) | flags
167
168bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address):
169    if page->mapping != ~0:
170        mem->unmap (page)
171    if address == ~0:
172        return true
173    if address >= 0x80000000:
174        dpanic (address, "trying to map to kernel address")
175        return false
176    if address & ~PAGE_MASK:
177        dpanic (address, "mapping not page-aligned")
178        address &= PAGE_MASK
179    if !mem->arch.directory:
180        //kdebug ("creating directory\n")
181        mem->arch.directory = (Table **)mem->zalloc ()
182        if !mem->arch.directory:
183            dpanic (0, "unable to allocate directory")
184            return false
185        mem->arch.shadow = (kPageP *)mem->zalloc ()
186        if !mem->arch.shadow:
187            dpanic (0, "unable to allocate shadow directory")
188            mem->zfree ((unsigned)mem->arch.directory)
189            mem->arch.directory = NULL
190            return false
191    Table *table = mem->arch.directory[address >> 21]
192    if !table:
193        //kdebug ("creating table\n")
194        table = (Table *)mem->zalloc ()
195        if !table:
196            dpanic (0, "unable to allocate table")
197            //if mem->arch.first_table == ~0:
198            // mem->zfree ((unsigned)mem->arch.directory)
199            // mem->zfree ((unsigned)mem->arch.shadow)
200            // mem->arch.directory = NULL
201            // mem->arch.shadow = NULL
202            return false
203        mem->arch.directory[address >> 21] = table
204    unsigned idx = (address >> 12) & ((1 << 9) - 1)
205    if table->entrylo[idx]:
206        kdebug ("page already mapped: ")
207        kdebug_num (idx, 3)
208        kdebug (";")
209        kdebug_num (table->entrylo[idx])
210        kdebug ("/")
211        kdebug_num ((unsigned)table->page[idx])
212        kdebug (" table: ")
213        kdebug_num ((unsigned)table)
214        kdebug ("\n")
215        mem->unmap (table->page[idx])
216    table->entrylo[idx] = make_entry_lo (page)
217    table->page[idx] = page
218    #if 0
219    kdebug ("mapped ")
220    kdebug_num (page->frame)
221    kdebug (" at address ")
222    kdebug_num (address)
223    kdebug ('\n')
224    #endif
225    page->mapping = address
226    page->arch.next_mapped = mem->arch.shadow[address >> 21]
227    if page->arch.next_mapped:
228        page->arch.next_mapped->arch.prev_mapped = page
229    mem->arch.shadow[address >> 21] = page
230    tlb_reset (mem, address, table->entrylo[idx])
231    return true
232
233void kMemory_arch_unmap (kMemory *mem, kPage *page):
234    //kdebug_line ()
235    unsigned didx = page->mapping >> 21
236    unsigned tidx = (page->mapping >> 12) & ((1 << 9) - 1)
237    Table *table = mem->arch.directory[didx]
238    table->entrylo[tidx] = 0
239    table->page[tidx] = NULL
240    if page->arch.next_mapped:
241        page->arch.next_mapped->arch.prev_mapped = page->arch.prev_mapped
242    if page->arch.prev_mapped:
243        page->arch.prev_mapped->arch.next_mapped = page->arch.next_mapped
244    else:
245        mem->arch.shadow[didx] = page->arch.next_mapped
246    page->arch.prev_mapped = NULL
247    page->arch.next_mapped = NULL
248    tlb_reset (mem, page->mapping, 0)
249    page->mapping = ~0
250
251kPage *kMemory_arch_get_mapping (kMemory *mem, unsigned address):
252    //kdebug_line ()
253    if address >= 0x80000000 || !mem->arch.directory:
254        return NULL
255    Table *table = mem->arch.directory[address >> 21]
256    if !table:
257        return NULL
258    return table->page[(address >> 12) & ((1 << 9) - 1)]
259
260void kPage_arch_update_mapping (kPage *page):
261    //kdebug_line ()
262    if page->mapping == ~0:
263        return
264    unsigned target = make_entry_lo (page)
265    unsigned de = page->mapping >> 21
266    unsigned te = (page->mapping >> 12) & ((1 << 9) - 1)
267    page->address_space->arch.directory[de]->entrylo[te] = target
268    tlb_reset (page->address_space, page->mapping, target)
269
270typedef unsigned cacheline[8]
271void arch_uncache_page (unsigned page):
272    for cacheline *line = (cacheline *)page; line < (cacheline *)(page + PAGE_SIZE); ++line:
273        __asm__ volatile ("lw $k0, %0; cache 0x10, 0($k0); cache 0x11, 0($k0)" :: "m"(line))
274
275void arch_register_interrupt (unsigned num, kReceiver *r):
276    arch_interrupt_receiver[num] = r
277    // And enable or disable the interrupt.
278    if r:
279        //if num != 0x18:
280        // kdebug ("enabled interrupt ")
281        // kdebug_num (num)
282        // kdebug (", state: ")
283        // kdebug_num (INTC_IMR)
284        // kdebug ("\n")
285        intc_unmask_irq (num)
286    else:
287        //kdebug ("disabled interrupt ")
288        //kdebug_num (num)
289        //kdebug ("\n")
290        intc_mask_irq (num)
291

Archive Download this file

Branches:
master



interactive