/trunk/kernel/arch/sparc64/src/mm/cache_asm.S |
---|
File deleted |
/trunk/kernel/arch/sparc64/src/mm/cache.c |
---|
File deleted |
/trunk/kernel/arch/sparc64/src/mm/tlb.c |
---|
54,10 → 54,10 |
#include <arch/mm/tsb.h> |
#endif |
static void dtlb_pte_copy(pte_t *t, bool ro); |
static void itlb_pte_copy(pte_t *t); |
static void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, const |
char *str); |
static void dtlb_pte_copy(pte_t *t, index_t index, bool ro); |
static void itlb_pte_copy(pte_t *t, index_t index); |
static void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, |
const char *str); |
static void do_fast_data_access_mmu_miss_fault(istate_t *istate, |
tlb_tag_access_reg_t tag, const char *str); |
static void do_fast_data_access_protection_fault(istate_t *istate, |
92,8 → 92,8 |
* @param locked True for permanent mappings, false otherwise. |
* @param cacheable True if the mapping is cacheable, false otherwise. |
*/ |
void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize, bool |
locked, bool cacheable) |
void dtlb_insert_mapping(uintptr_t page, uintptr_t frame, int pagesize, |
bool locked, bool cacheable) |
{ |
tlb_tag_access_reg_t tag; |
tlb_data_t data; |
127,10 → 127,11 |
/** Copy PTE to TLB. |
* |
* @param t Page Table Entry to be copied. |
* @param ro If true, the entry will be created read-only, regardless of its w |
* field. |
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage. |
* @param ro If true, the entry will be created read-only, regardless of its |
* w field. |
*/ |
void dtlb_pte_copy(pte_t *t, bool ro) |
void dtlb_pte_copy(pte_t *t, index_t index, bool ro) |
{ |
tlb_tag_access_reg_t tag; |
tlb_data_t data; |
137,8 → 138,8 |
page_address_t pg; |
frame_address_t fr; |
pg.address = t->page; |
fr.address = t->frame; |
pg.address = t->page + (index << MMU_PAGE_WIDTH); |
fr.address = t->frame + (index << MMU_PAGE_WIDTH); |
tag.value = 0; |
tag.context = t->as->asid; |
165,8 → 166,9 |
/** Copy PTE to ITLB. |
* |
* @param t Page Table Entry to be copied. |
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage. |
*/ |
void itlb_pte_copy(pte_t *t) |
void itlb_pte_copy(pte_t *t, index_t index) |
{ |
tlb_tag_access_reg_t tag; |
tlb_data_t data; |
173,8 → 175,8 |
page_address_t pg; |
frame_address_t fr; |
pg.address = t->page; |
fr.address = t->frame; |
pg.address = t->page + (index << MMU_PAGE_WIDTH); |
fr.address = t->frame + (index << MMU_PAGE_WIDTH); |
tag.value = 0; |
tag.context = t->as->asid; |
199,6 → 201,7 |
void fast_instruction_access_mmu_miss(int n, istate_t *istate) |
{ |
uintptr_t va = ALIGN_DOWN(istate->tpc, PAGE_SIZE); |
index_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE; |
pte_t *t; |
page_table_lock(AS, true); |
209,9 → 212,9 |
* Insert it into ITLB. |
*/ |
t->a = true; |
itlb_pte_copy(t); |
itlb_pte_copy(t, index); |
#ifdef CONFIG_TSB |
itsb_pte_copy(t); |
itsb_pte_copy(t, index); |
#endif |
page_table_unlock(AS, true); |
} else { |
236,10 → 239,12 |
{ |
tlb_tag_access_reg_t tag; |
uintptr_t va; |
index_t index; |
pte_t *t; |
tag.value = dtlb_tag_access_read(); |
va = tag.vpn << PAGE_WIDTH; |
va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE); |
index = tag.vpn % MMU_PAGES_PER_PAGE; |
if (tag.context == ASID_KERNEL) { |
if (!tag.vpn) { |
259,14 → 264,15 |
* Insert it into DTLB. |
*/ |
t->a = true; |
dtlb_pte_copy(t, true); |
dtlb_pte_copy(t, index, true); |
#ifdef CONFIG_TSB |
dtsb_pte_copy(t, true); |
dtsb_pte_copy(t, index, true); |
#endif |
page_table_unlock(AS, true); |
} else { |
/* |
* Forward the page fault to the address space page fault handler. |
* Forward the page fault to the address space page fault |
* handler. |
*/ |
page_table_unlock(AS, true); |
if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) { |
281,10 → 287,12 |
{ |
tlb_tag_access_reg_t tag; |
uintptr_t va; |
index_t index; |
pte_t *t; |
tag.value = dtlb_tag_access_read(); |
va = tag.vpn << PAGE_WIDTH; |
va = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE); |
index = tag.vpn % MMU_PAGES_PER_PAGE; /* 16K-page emulation */ |
page_table_lock(AS, true); |
t = page_mapping_find(AS, va); |
296,10 → 304,11 |
*/ |
t->a = true; |
t->d = true; |
dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY, va); |
dtlb_pte_copy(t, false); |
dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY, |
va + index * MMU_PAGE_SIZE); |
dtlb_pte_copy(t, index, false); |
#ifdef CONFIG_TSB |
dtsb_pte_copy(t, false); |
dtsb_pte_copy(t, index, false); |
#endif |
page_table_unlock(AS, true); |
} else { |
348,8 → 357,8 |
} |
void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, const char |
*str) |
void do_fast_instruction_access_mmu_miss_fault(istate_t *istate, |
const char *str) |
{ |
fault_if_from_uspace(istate, "%s\n", str); |
dump_istate(istate); |
356,12 → 365,12 |
panic("%s\n", str); |
} |
void do_fast_data_access_mmu_miss_fault(istate_t *istate, tlb_tag_access_reg_t |
tag, const char *str) |
void do_fast_data_access_mmu_miss_fault(istate_t *istate, |
tlb_tag_access_reg_t tag, const char *str) |
{ |
uintptr_t va; |
va = tag.vpn << PAGE_WIDTH; |
va = tag.vpn << MMU_PAGE_WIDTH; |
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va, |
tag.context); |
370,12 → 379,12 |
panic("%s\n", str); |
} |
void do_fast_data_access_protection_fault(istate_t *istate, tlb_tag_access_reg_t |
tag, const char *str) |
void do_fast_data_access_protection_fault(istate_t *istate, |
tlb_tag_access_reg_t tag, const char *str) |
{ |
uintptr_t va; |
va = tag.vpn << PAGE_WIDTH; |
va = tag.vpn << MMU_PAGE_WIDTH; |
fault_if_from_uspace(istate, "%s, Page=%p (ASID=%d)\n", str, va, |
tag.context); |
481,11 → 490,11 |
ctx.context = asid; |
mmu_primary_context_write(ctx.v); |
for (i = 0; i < cnt; i++) { |
for (i = 0; i < cnt * MMU_PAGES_PER_PAGE; i++) { |
itlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_PRIMARY, |
page + i * PAGE_SIZE); |
page + i * MMU_PAGE_SIZE); |
dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_PRIMARY, |
page + i * PAGE_SIZE); |
page + i * MMU_PAGE_SIZE); |
} |
mmu_primary_context_write(pc_save.v); |
/trunk/kernel/arch/sparc64/src/mm/as.c |
---|
62,7 → 62,7 |
{ |
#ifdef CONFIG_TSB |
int order = fnzb32(((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * |
sizeof(tsb_entry_t)) >> FRAME_WIDTH); |
sizeof(tsb_entry_t)) >> MMU_FRAME_WIDTH); |
uintptr_t tsb = (uintptr_t) frame_alloc(order, flags | FRAME_KA); |
if (!tsb) |
71,8 → 71,8 |
as->arch.itsb = (tsb_entry_t *) tsb; |
as->arch.dtsb = (tsb_entry_t *) (tsb + ITSB_ENTRY_COUNT * |
sizeof(tsb_entry_t)); |
memsetb((uintptr_t) as->arch.itsb, (ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) |
* sizeof(tsb_entry_t), 0); |
memsetb((uintptr_t) as->arch.itsb, |
(ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * sizeof(tsb_entry_t), 0); |
#endif |
return 0; |
} |
81,7 → 81,7 |
{ |
#ifdef CONFIG_TSB |
count_t cnt = ((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * |
sizeof(tsb_entry_t)) >> FRAME_WIDTH; |
sizeof(tsb_entry_t)) >> MMU_FRAME_WIDTH; |
frame_free(KA2PA((uintptr_t) as->arch.itsb)); |
return cnt; |
#else |
139,7 → 139,7 |
uintptr_t tsb = (uintptr_t) as->arch.itsb; |
if (!overlaps(tsb, 8 * PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) { |
if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) { |
/* |
* TSBs were allocated from memory not covered |
* by the locked 4M kernel DTLB entry. We need |
158,9 → 158,9 |
tsb_base.size = TSB_SIZE; |
tsb_base.split = 0; |
tsb_base.base = ((uintptr_t) as->arch.itsb) >> PAGE_WIDTH; |
tsb_base.base = ((uintptr_t) as->arch.itsb) >> MMU_PAGE_WIDTH; |
itsb_base_write(tsb_base.value); |
tsb_base.base = ((uintptr_t) as->arch.dtsb) >> PAGE_WIDTH; |
tsb_base.base = ((uintptr_t) as->arch.dtsb) >> MMU_PAGE_WIDTH; |
dtsb_base_write(tsb_base.value); |
#endif |
} |
189,7 → 189,7 |
uintptr_t tsb = (uintptr_t) as->arch.itsb; |
if (!overlaps(tsb, 8 * PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) { |
if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) { |
/* |
* TSBs were allocated from memory not covered |
* by the locked 4M kernel DTLB entry. We need |
/trunk/kernel/arch/sparc64/src/mm/cache.S |
---|
0,0 → 1,91 |
/* |
* Copyright (c) 2006 Jakub Jermar |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <arch/arch.h> |
#define DCACHE_SIZE (16 * 1024) |
#define DCACHE_LINE_SIZE 32 |
#define DCACHE_TAG_SHIFT 2 |
.register %g2, #scratch |
.register %g3, #scratch |
/** Flush the whole D-cache. */ |
.global dcache_flush |
dcache_flush: |
set (DCACHE_SIZE - DCACHE_LINE_SIZE), %g1 |
stxa %g0, [%g1] ASI_DCACHE_TAG |
0: membar #Sync |
subcc %g1, DCACHE_LINE_SIZE, %g1 |
bnz,pt %xcc, 0b |
stxa %g0, [%g1] ASI_DCACHE_TAG |
retl |
membar #Sync |
/** Flush only D-cache lines of one virtual color. |
* |
* @param o0 Virtual color to be flushed. |
*/ |
.global dcache_flush_color |
dcache_flush_color: |
mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1 |
set DCACHE_SIZE / 2, %g2 |
sllx %g2, %o0, %g2 |
sub %g2, DCACHE_LINE_SIZE, %g2 |
0: stxa %g0, [%g2] ASI_DCACHE_TAG |
membar #Sync |
subcc %g1, 1, %g1 |
bnz,pt %xcc, 0b |
sub %g2, DCACHE_LINE_SIZE, %g2 |
retl |
nop |
/** Flush only D-cache lines of one virtual color and one tag. |
* |
* @param o0 Virtual color to lookup the tag. |
* @param o1 Tag of the cachelines to be flushed. |
*/ |
.global dcache_flush_tag |
dcache_flush_tag: |
mov (DCACHE_SIZE / DCACHE_LINE_SIZE) / 2, %g1 |
set DCACHE_SIZE / 2, %g2 |
sllx %g2, %o0, %g2 |
sub %g2, DCACHE_LINE_SIZE, %g2 |
0: ldxa [%g2] ASI_DCACHE_TAG, %g3 |
srlx %g3, DCACHE_TAG_SHIFT, %g3 |
cmp %g3, %o1 |
bnz 1f |
nop |
stxa %g0, [%g2] ASI_DCACHE_TAG |
membar #Sync |
1: subcc %g1, 1, %g1 |
bnz,pt %xcc, 0b |
sub %g2, DCACHE_LINE_SIZE, %g2 |
retl |
nop |
/trunk/kernel/arch/sparc64/src/mm/tsb.c |
---|
34,6 → 34,7 |
#include <arch/mm/tsb.h> |
#include <arch/mm/tlb.h> |
#include <arch/mm/page.h> |
#include <arch/barrier.h> |
#include <mm/as.h> |
#include <arch/types.h> |
40,7 → 41,7 |
#include <macros.h> |
#include <debug.h> |
#define TSB_INDEX_MASK ((1 << (21 + 1 + TSB_SIZE - PAGE_WIDTH)) - 1) |
#define TSB_INDEX_MASK ((1 << (21 + 1 + TSB_SIZE - MMU_PAGE_WIDTH)) - 1) |
/** Invalidate portion of TSB. |
* |
59,8 → 60,8 |
ASSERT(as->arch.itsb && as->arch.dtsb); |
i0 = (page >> PAGE_WIDTH) & TSB_INDEX_MASK; |
cnt = min(pages, ITSB_ENTRY_COUNT); |
i0 = (page >> MMU_PAGE_WIDTH) & TSB_INDEX_MASK; |
cnt = min(pages * MMU_PAGES_PER_PAGE, ITSB_ENTRY_COUNT); |
for (i = 0; i < cnt; i++) { |
as->arch.itsb[(i0 + i) & (ITSB_ENTRY_COUNT - 1)].tag.invalid = |
73,14 → 74,17 |
/** Copy software PTE to ITSB. |
* |
* @param t Software PTE. |
* @param index Zero if lower 8K-subpage, one if higher 8K subpage. |
*/ |
void itsb_pte_copy(pte_t *t) |
void itsb_pte_copy(pte_t *t, index_t index) |
{ |
as_t *as; |
tsb_entry_t *tsb; |
index_t entry; |
as = t->as; |
tsb = &as->arch.itsb[(t->page >> PAGE_WIDTH) & TSB_INDEX_MASK]; |
entry = ((t->page >> MMU_PAGE_WIDTH) + index) & TSB_INDEX_MASK; |
tsb = &as->arch.itsb[entry]; |
/* |
* We use write barriers to make sure that the TSB load |
95,10 → 99,11 |
write_barrier(); |
tsb->tag.context = as->asid; |
tsb->tag.va_tag = t->page >> VA_TAG_PAGE_SHIFT; |
tsb->tag.va_tag = (t->page + (index << MMU_PAGE_WIDTH)) >> |
VA_TAG_PAGE_SHIFT; |
tsb->data.value = 0; |
tsb->data.size = PAGESIZE_8K; |
tsb->data.pfn = t->frame >> FRAME_WIDTH; |
tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index; |
tsb->data.cp = t->c; |
tsb->data.p = t->k; /* p as privileged */ |
tsb->data.v = t->p; |
111,15 → 116,18 |
/** Copy software PTE to DTSB. |
* |
* @param t Software PTE. |
* @param index Zero if lower 8K-subpage, one if higher 8K-subpage. |
* @param ro If true, the mapping is copied read-only. |
*/ |
void dtsb_pte_copy(pte_t *t, bool ro) |
void dtsb_pte_copy(pte_t *t, index_t index, bool ro) |
{ |
as_t *as; |
tsb_entry_t *tsb; |
index_t entry; |
as = t->as; |
tsb = &as->arch.dtsb[(t->page >> PAGE_WIDTH) & TSB_INDEX_MASK]; |
entry = ((t->page >> MMU_PAGE_WIDTH) + index) & TSB_INDEX_MASK; |
tsb = &as->arch.dtsb[entry]; |
/* |
* We use write barriers to make sure that the TSB load |
134,10 → 142,11 |
write_barrier(); |
tsb->tag.context = as->asid; |
tsb->tag.va_tag = t->page >> VA_TAG_PAGE_SHIFT; |
tsb->tag.va_tag = (t->page + (index << MMU_PAGE_WIDTH)) >> |
VA_TAG_PAGE_SHIFT; |
tsb->data.value = 0; |
tsb->data.size = PAGESIZE_8K; |
tsb->data.pfn = t->frame >> FRAME_WIDTH; |
tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index; |
tsb->data.cp = t->c; |
#ifdef CONFIG_VIRT_IDX_DCACHE |
tsb->data.cv = t->c; |
/trunk/kernel/arch/sparc64/src/mm/page.c |
---|
108,25 → 108,25 |
count_t count; |
} sizemap[] = { |
{ PAGESIZE_8K, 0, 1 }, /* 8K */ |
{ PAGESIZE_8K, PAGE_SIZE, 2 }, /* 16K */ |
{ PAGESIZE_8K, PAGE_SIZE, 4 }, /* 32K */ |
{ PAGESIZE_8K, MMU_PAGE_SIZE, 2 }, /* 16K */ |
{ PAGESIZE_8K, MMU_PAGE_SIZE, 4 }, /* 32K */ |
{ PAGESIZE_64K, 0, 1}, /* 64K */ |
{ PAGESIZE_64K, 8 * PAGE_SIZE, 2 }, /* 128K */ |
{ PAGESIZE_64K, 8 * PAGE_SIZE, 4 }, /* 256K */ |
{ PAGESIZE_64K, 8 * MMU_PAGE_SIZE, 2 }, /* 128K */ |
{ PAGESIZE_64K, 8 * MMU_PAGE_SIZE, 4 }, /* 256K */ |
{ PAGESIZE_512K, 0, 1 }, /* 512K */ |
{ PAGESIZE_512K, 64 * PAGE_SIZE, 2 }, /* 1M */ |
{ PAGESIZE_512K, 64 * PAGE_SIZE, 4 }, /* 2M */ |
{ PAGESIZE_512K, 64 * MMU_PAGE_SIZE, 2 }, /* 1M */ |
{ PAGESIZE_512K, 64 * MMU_PAGE_SIZE, 4 }, /* 2M */ |
{ PAGESIZE_4M, 0, 1 }, /* 4M */ |
{ PAGESIZE_4M, 512 * PAGE_SIZE, 2 } /* 8M */ |
{ PAGESIZE_4M, 512 * MMU_PAGE_SIZE, 2 } /* 8M */ |
}; |
ASSERT(ALIGN_UP(physaddr, PAGE_SIZE) == physaddr); |
ASSERT(ALIGN_UP(physaddr, MMU_PAGE_SIZE) == physaddr); |
ASSERT(size <= 8 * 1024 * 1024); |
if (size <= FRAME_SIZE) |
if (size <= MMU_FRAME_SIZE) |
order = 0; |
else |
order = (fnzb64(size - 1) + 1) - FRAME_WIDTH; |
order = (fnzb64(size - 1) + 1) - MMU_FRAME_WIDTH; |
/* |
* Use virtual addresses that are beyond the limit of physical memory. |
134,8 → 134,10 |
* by frame_alloc(). |
*/ |
ASSERT(PA2KA(last_frame)); |
uintptr_t virtaddr = ALIGN_UP(PA2KA(last_frame), 1 << (order + FRAME_WIDTH)); |
last_frame = ALIGN_UP(KA2PA(virtaddr) + size, 1 << (order + FRAME_WIDTH)); |
uintptr_t virtaddr = ALIGN_UP(PA2KA(last_frame), |
1 << (order + FRAME_WIDTH)); |
last_frame = ALIGN_UP(KA2PA(virtaddr) + size, |
1 << (order + FRAME_WIDTH)); |
for (i = 0; i < sizemap[order].count; i++) { |
/* |