1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-11-16 23:35:21 +02:00
iris/mips/arch.ccp

268 lines
7.6 KiB
Plaintext
Raw Normal View History

2009-05-20 23:07:56 +03:00
#pypp 0
2009-06-01 15:26:42 +03:00
// Iris: micro-kernel for a capability-based operating system.
// mips/arch.ccp: Most mips-specific parts.
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
2009-05-22 23:48:49 +03:00
#define ARCH
#include "kernel.hh"
2009-05-20 23:07:56 +03:00
void kThread_arch_init (kThread *thread):
2009-05-20 23:07:56 +03:00
thread->arch.at = 0
2009-08-24 22:02:35 +03:00
for unsigned i = 0; i < 2; ++i:
thread->arch.v[i] = 0
thread->arch.k[i] = 0
for unsigned i = 0; i < 4; ++i:
thread->arch.a[i] = 0
for unsigned i = 0; i < 10; ++i:
thread->arch.t[i] = 0
2009-05-20 23:07:56 +03:00
thread->arch.gp = 0
thread->arch.fp = 0
thread->arch.ra = 0
thread->arch.hi = 0
thread->arch.lo = 0
2010-01-18 06:01:59 +02:00
void kPage_arch_init (kPage *page):
page->arch.prev_mapped = NULL
page->arch.next_mapped = NULL
2009-09-06 12:04:09 +03:00
void kThread_arch_receive (kThread *thread, Kernel::Num protected_data, Kernel::Num *data):
2009-08-24 22:02:35 +03:00
thread->arch.a[0] = data[0].l
thread->arch.a[1] = data[0].h
thread->arch.a[2] = data[1].l
thread->arch.a[3] = data[1].h
2009-09-06 12:04:09 +03:00
thread->arch.t[0] = protected_data.l
thread->arch.t[1] = protected_data.h
2009-05-25 01:31:35 +03:00
unsigned *kThread_arch_info (kThread *thread, unsigned num):
2009-05-27 19:33:05 +03:00
switch num:
case 1:
return &thread->arch.at
case 2:
2009-08-24 22:02:35 +03:00
return &thread->arch.v[0]
2009-05-27 19:33:05 +03:00
case 3:
2009-08-24 22:02:35 +03:00
return &thread->arch.v[1]
2009-05-27 19:33:05 +03:00
case 4:
2009-08-24 22:02:35 +03:00
return &thread->arch.a[0]
2009-05-27 19:33:05 +03:00
case 5:
2009-08-24 22:02:35 +03:00
return &thread->arch.a[1]
2009-05-27 19:33:05 +03:00
case 6:
2009-08-24 22:02:35 +03:00
return &thread->arch.a[2]
2009-05-27 19:33:05 +03:00
case 7:
2009-08-24 22:02:35 +03:00
return &thread->arch.a[3]
2009-05-27 19:33:05 +03:00
case 8:
2009-08-24 22:02:35 +03:00
return &thread->arch.t[0]
2009-05-27 19:33:05 +03:00
case 9:
2009-08-24 22:02:35 +03:00
return &thread->arch.t[1]
2009-05-27 19:33:05 +03:00
case 10:
2009-08-24 22:02:35 +03:00
return &thread->arch.t[2]
2009-05-27 19:33:05 +03:00
case 11:
2009-08-24 22:02:35 +03:00
return &thread->arch.t[3]
2009-05-27 19:33:05 +03:00
case 12:
2009-08-24 22:02:35 +03:00
return &thread->arch.t[4]
2009-05-27 19:33:05 +03:00
case 13:
2009-08-24 22:02:35 +03:00
return &thread->arch.t[5]
2009-05-27 19:33:05 +03:00
case 14:
2009-08-24 22:02:35 +03:00
return &thread->arch.t[6]
2009-05-27 19:33:05 +03:00
case 15:
2009-08-24 22:02:35 +03:00
return &thread->arch.t[7]
2009-05-27 19:33:05 +03:00
case 16:
2009-08-24 22:02:35 +03:00
return &thread->arch.s[0]
2009-05-27 19:33:05 +03:00
case 17:
2009-08-24 22:02:35 +03:00
return &thread->arch.s[1]
2009-05-27 19:33:05 +03:00
case 18:
2009-08-24 22:02:35 +03:00
return &thread->arch.s[2]
2009-05-27 19:33:05 +03:00
case 19:
2009-08-24 22:02:35 +03:00
return &thread->arch.s[3]
2009-05-27 19:33:05 +03:00
case 20:
2009-08-24 22:02:35 +03:00
return &thread->arch.s[4]
2009-05-27 19:33:05 +03:00
case 21:
2009-08-24 22:02:35 +03:00
return &thread->arch.s[5]
2009-05-27 19:33:05 +03:00
case 22:
2009-08-24 22:02:35 +03:00
return &thread->arch.s[6]
2009-05-27 19:33:05 +03:00
case 23:
2009-08-24 22:02:35 +03:00
return &thread->arch.s[7]
2009-05-27 19:33:05 +03:00
case 24:
2009-08-24 22:02:35 +03:00
return &thread->arch.t[8]
2009-05-27 19:33:05 +03:00
case 25:
2009-08-24 22:02:35 +03:00
return &thread->arch.t[9]
2009-05-27 19:33:05 +03:00
case 26:
2009-08-24 22:02:35 +03:00
return &thread->arch.k[0]
2009-05-27 19:33:05 +03:00
case 27:
2009-08-24 22:02:35 +03:00
return &thread->arch.k[1]
2009-05-27 19:33:05 +03:00
case 28:
return &thread->arch.gp
case 29:
return &thread->sp
case 30:
return &thread->arch.fp
case 31:
return &thread->arch.ra
default:
return NULL
void kMemory_arch_init (kMemory *mem):
2009-05-24 13:22:22 +03:00
mem->arch.asid = 1
2009-05-20 23:07:56 +03:00
mem->arch.directory = NULL
mem->arch.shadow = NULL
2009-05-20 23:07:56 +03:00
2010-01-17 11:01:42 +02:00
static void tlb_reset (kMemory *mem, unsigned address, unsigned value):
2009-12-30 23:41:45 +02:00
//dbg_log_line ()
2010-01-17 11:01:42 +02:00
unsigned asid = mem->arch.asid
if asids[asid] != (unsigned)mem:
//dbg_log ("not resetting tlb, because the asid is not in use.\n")
return
//dbg_log ("resetting tlb for ")
//dbg_log_num (address)
//dbg_log ("\n")
2009-06-01 02:12:54 +03:00
cp0_set (CP0_ENTRY_HI, address | asid)
__asm__ volatile ("tlbp")
unsigned idx
cp0_get (CP0_INDEX, idx)
if ~idx & 0x80000000:
2010-01-17 11:01:42 +02:00
__asm__ volatile ("tlbr")
2009-06-01 02:12:54 +03:00
if address & (1 << PAGE_BITS):
cp0_set (CP0_ENTRY_LO1, value)
else:
cp0_set (CP0_ENTRY_LO0, value)
__asm__ volatile ("tlbwi")
2010-01-17 11:01:42 +02:00
static unsigned make_entry_lo (kPage *page):
2009-12-30 23:41:45 +02:00
//dbg_log_line ()
if !page->frame:
2010-01-17 11:01:42 +02:00
//dbg_log ("not mapping because there is no frame\n")
2009-06-01 02:12:54 +03:00
return 0
unsigned flags
2009-09-06 12:04:09 +03:00
if page->flags & Kernel::Page::UNCACHED:
2009-06-08 14:46:13 +03:00
flags = 0x10 | 0x2
else:
2009-10-31 10:32:23 +02:00
// 18 is write-back cache; 00 is write-through cache.
2009-06-01 02:12:54 +03:00
flags = 0x18 | 0x2
2010-01-17 11:01:42 +02:00
if ~page->flags & Kernel::Page::MAPPED_READONLY:
2009-06-08 14:46:13 +03:00
flags |= 0x4
return ((page->frame & ~0x80000000) >> 6) | flags
2009-06-01 02:12:54 +03:00
2010-01-17 11:01:42 +02:00
bool kMemory_arch_map (kMemory *mem, kPage *page, unsigned address):
2009-12-30 23:41:45 +02:00
//dbg_log_line ()
2009-06-01 02:12:54 +03:00
if address >= 0x80000000:
2010-01-16 17:13:54 +02:00
dpanic (address, "trying to map to kernel address")
2009-06-01 02:12:54 +03:00
return false
2010-01-17 11:01:42 +02:00
if page->mapping != ~0:
mem->unmap (page)
if address == ~0:
return true
if address & ~PAGE_MASK:
dpanic (address, "mapping not page-aligned")
address &= PAGE_MASK
2009-05-23 21:55:31 +03:00
if !mem->arch.directory:
2010-01-17 11:01:42 +02:00
//dbg_log ("creating directory\n")
mem->arch.directory = (Table **)mem->zalloc ()
2009-05-23 21:55:31 +03:00
if !mem->arch.directory:
2010-01-17 11:01:42 +02:00
dpanic (0, "unable to allocate directory")
2009-05-23 21:55:31 +03:00
return false
2010-01-17 11:01:42 +02:00
mem->arch.shadow = (kPageP *)mem->zalloc ()
if !mem->arch.shadow:
2010-01-17 11:01:42 +02:00
dpanic (0, "unable to allocate shadow directory")
mem->zfree ((unsigned)mem->arch.directory)
mem->arch.directory = NULL
return false
2010-01-17 11:01:42 +02:00
Table *table = mem->arch.directory[address >> 21]
2009-05-20 23:07:56 +03:00
if !table:
2010-01-17 11:01:42 +02:00
//dbg_log ("creating table\n")
table = (Table *)mem->zalloc ()
2009-05-20 23:07:56 +03:00
if !table:
2010-01-17 11:01:42 +02:00
dpanic (0, "unable to allocate table")
//if mem->arch.first_table == ~0:
// mem->zfree ((unsigned)mem->arch.directory)
// mem->zfree ((unsigned)mem->arch.shadow)
// mem->arch.directory = NULL
// mem->arch.shadow = NULL
2009-05-20 23:07:56 +03:00
return false
mem->arch.directory[address >> 21] = table
unsigned idx = (address >> 12) & ((1 << 9) - 1)
2010-01-17 11:01:42 +02:00
if table->entrylo[idx]:
2009-12-30 23:41:45 +02:00
dbg_log ("page already mapped: ")
dbg_log_num (idx, 3)
dbg_log (";")
2010-01-17 11:01:42 +02:00
dbg_log_num (table->entrylo[idx])
2009-12-30 23:41:45 +02:00
dbg_log ("/")
2010-01-17 11:01:42 +02:00
dbg_log_num ((unsigned)table->page[idx])
2009-12-30 23:41:45 +02:00
dbg_log (" table: ")
dbg_log_num ((unsigned)table)
dbg_log ("\n")
2010-01-17 11:01:42 +02:00
mem->unmap (table->page[idx])
table->entrylo[idx] = make_entry_lo (page)
table->page[idx] = page
//dbg_log ("mapped at address ")
//dbg_log_num (address)
//dbg_log_char ('\n')
page->mapping = address
page->arch.next_mapped = mem->arch.shadow[address >> 21]
if page->arch.next_mapped:
page->arch.next_mapped->arch.prev_mapped = page
mem->arch.shadow[address >> 21] = page
tlb_reset (mem, address, table->entrylo[idx])
2009-05-23 21:55:31 +03:00
return true
2009-05-20 23:07:56 +03:00
2010-01-17 11:01:42 +02:00
void kMemory_arch_unmap (kMemory *mem, kPage *page):
2009-12-30 23:41:45 +02:00
//dbg_log_line ()
2010-01-17 11:01:42 +02:00
unsigned didx = page->mapping >> 21
unsigned tidx = (page->mapping >> 12) & ((1 << 9) - 1)
Table *table = mem->arch.directory[didx]
table->entrylo[tidx] = 0
table->page[tidx] = NULL
if page->arch.next_mapped:
page->arch.next_mapped->arch.prev_mapped = page->arch.prev_mapped
if page->arch.prev_mapped:
page->arch.prev_mapped->arch.next_mapped = page->arch.next_mapped
else:
mem->arch.shadow[didx] = page->arch.next_mapped
page->arch.prev_mapped = NULL
page->arch.next_mapped = NULL
tlb_reset (mem, page->mapping, 0)
page->mapping = ~0
2009-05-20 23:07:56 +03:00
2010-01-17 11:01:42 +02:00
kPage *kMemory_arch_get_mapping (kMemory *mem, unsigned address):
2009-12-30 23:41:45 +02:00
//dbg_log_line ()
2009-12-27 01:12:35 +02:00
if address >= 0x80000000 || !mem->arch.directory:
2009-06-01 02:12:54 +03:00
return NULL
2010-01-17 11:01:42 +02:00
Table *table = mem->arch.directory[address >> 21]
2009-12-27 01:12:35 +02:00
if !table:
return NULL
2010-01-17 11:01:42 +02:00
return table->page[(address >> 12) & ((1 << 9) - 1)]
2009-05-20 23:07:56 +03:00
void kPage_arch_update_mapping (kPage *page):
2009-12-30 23:41:45 +02:00
//dbg_log_line ()
2010-01-17 11:01:42 +02:00
if page->mapping == ~0:
2009-06-01 02:12:54 +03:00
return
2010-01-17 11:01:42 +02:00
unsigned target = make_entry_lo (page)
unsigned de = page->mapping >> 21
unsigned te = (page->mapping >> 12) & ((1 << 9) - 1)
page->address_space->arch.directory[de]->entrylo[te] = target
tlb_reset (page->address_space, page->mapping, target)
2009-05-29 00:35:27 +03:00
2009-12-30 23:41:45 +02:00
typedef unsigned cacheline[8]
void arch_uncache_page (unsigned page):
for cacheline *line = (cacheline *)page; line < (cacheline *)(page + PAGE_SIZE); ++line:
__asm__ volatile ("lw $k0, %0; cache 0x10, 0($k0); cache 0x11, 0($k0)" :: "m"(line))
void arch_register_interrupt (unsigned num, kReceiver *r):
2009-05-27 19:33:05 +03:00
arch_interrupt_receiver[num] = r
2009-06-01 02:12:54 +03:00
// And enable or disable the interrupt.
if r:
2009-07-04 17:21:28 +03:00
intc_unmask_irq (num)
2009-06-01 02:12:54 +03:00
else:
2009-07-04 17:21:28 +03:00
intc_mask_irq (num)