Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3862 → Rev 3861

/branches/sparc/kernel/arch/sparc64/src/mm/sun4v/as.c
33,16 → 33,14
/** @file
*/
 
/* SUN4V-OK */
 
#include <arch/mm/as.h>
#include <arch/mm/pagesize.h>
#include <arch/mm/tlb.h>
#include <arch/mm/sun4u/tlb.h>
#include <arch/mm/sun4u/tlb.h>
#include <genarch/mm/page_ht.h>
#include <genarch/mm/asid_fifo.h>
#include <debug.h>
#include <config.h>
#include <arch/sun4v/hypercall.h>
 
#ifdef CONFIG_TSB
#include <arch/mm/tsb.h>
65,8 → 63,12
int as_constructor_arch(as_t *as, int flags)
{
#ifdef CONFIG_TSB
int order = fnzb32(
(TSB_ENTRY_COUNT * sizeof(tsb_entry_t)) >> FRAME_WIDTH);
/*
* The order must be calculated with respect to the emulated
* 16K page size.
*/
int order = fnzb32(((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
sizeof(tsb_entry_t)) >> FRAME_WIDTH);
 
uintptr_t tsb = (uintptr_t) frame_alloc(order, flags | FRAME_KA);
 
73,15 → 75,12
if (!tsb)
return -1;
 
as->arch.tsb_description.page_size = PAGESIZE_8K;
as->arch.tsb_description.associativity = 1;
as->arch.tsb_description.num_ttes = TSB_ENTRY_COUNT;
as->arch.tsb_description.pgsize_mask = 1 << PAGESIZE_8K;
as->arch.tsb_description.tsb_base = tsb;
as->arch.tsb_description.reserved = 0;
as->arch.itsb = (tsb_entry_t *) tsb;
as->arch.dtsb = (tsb_entry_t *) (tsb + ITSB_ENTRY_COUNT *
sizeof(tsb_entry_t));
 
memsetb((void *) as->arch.tsb_description.tsb_base,
TSB_ENTRY_COUNT * sizeof(tsb_entry_t), 0);
memsetb(as->arch.itsb,
(ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * sizeof(tsb_entry_t), 0);
#endif
return 0;
}
89,8 → 88,13
int as_destructor_arch(as_t *as)
{
#ifdef CONFIG_TSB
count_t cnt = (TSB_ENTRY_COUNT * sizeof(tsb_entry_t)) >> FRAME_WIDTH;
frame_free(KA2PA((uintptr_t) as->arch.tsb_description.tsb_base));
/*
* The count must be calculated with respect to the emualted 16K page
* size.
*/
count_t cnt = ((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
sizeof(tsb_entry_t)) >> FRAME_WIDTH;
frame_free(KA2PA((uintptr_t) as->arch.itsb));
return cnt;
#else
return 0;
101,7 → 105,6
{
#ifdef CONFIG_TSB
tsb_invalidate(as, 0, (count_t) -1);
as->arch.tsb_description.context = as->asid;
#endif
return 0;
}
115,13 → 118,32
*/
void as_install_arch(as_t *as)
{
mmu_secondary_context_write(as->asid);
#if 0
tlb_context_reg_t ctx;
/*
* Note that we don't and may not lock the address space. That's ok
* since we only read members that are currently read-only.
*
* Moreover, the as->asid is protected by asidlock, which is being held.
*/
/*
* Write ASID to secondary context register. The primary context
* register has to be set from TL>0 so it will be filled from the
* secondary context register from the TL=1 code just before switch to
* userspace.
*/
ctx.v = 0;
ctx.context = as->asid;
mmu_secondary_context_write(ctx.v);
 
#ifdef CONFIG_TSB
uintptr_t base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH);
 
ASSERT(as->arch.tsb_description.tsb_base);
uintptr_t tsb = as->arch.tsb_description.tsb_base;
ASSERT(as->arch.itsb && as->arch.dtsb);
 
uintptr_t tsb = (uintptr_t) as->arch.itsb;
if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
/*
129,15 → 151,43
* by the locked 4M kernel DTLB entry. We need
* to map both TSBs explicitly.
*/
mmu_demap_page(tsb, 0, MMU_FLAG_DTLB);
mmu_map_perm_addr(
tsb, KA2PA(tsb), true, true, false, true,
PAGESIZE_64K, MMU_FLAG_DTLB);
dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, tsb);
dtlb_insert_mapping(tsb, KA2PA(tsb), PAGESIZE_64K, true, true);
}
/*
* Setup TSB Base registers.
*/
tsb_base_reg_t tsb_base;
tsb_base.value = 0;
tsb_base.size = TSB_SIZE;
tsb_base.split = 0;
 
__hypercall_fast2(MMU_TSB_CTX0, 1, as->arch.tsb_description.tsb_base);
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) >> MMU_PAGE_WIDTH;
dtsb_base_write(tsb_base.value);
#if defined (US3)
/*
* Clear the extension registers.
* In HelenOS, primary and secondary context registers contain
* equal values and kernel misses (context 0, ie. the nucleus context)
* are excluded from the TSB miss handler, so it makes no sense
* to have separate TSBs for primary, secondary and nucleus contexts.
* Clearing the extension registers will ensure that the value of the
* TSB Base register will be used as an address of TSB, making the code
* compatible with the US port.
*/
itsb_primary_extension_write(0);
itsb_nucleus_extension_write(0);
dtsb_primary_extension_write(0);
dtsb_secondary_extension_write(0);
dtsb_nucleus_extension_write(0);
#endif
#endif
#endif
}
 
/** Perform sparc64-specific tasks when an address space is removed from the
149,6 → 199,7
*/
void as_deinstall_arch(as_t *as)
{
 
/*
* Note that we don't and may not lock the address space. That's ok
* since we only read members that are currently read-only.
155,12 → 206,13
*
* Moreover, the as->asid is protected by asidlock, which is being held.
*/
 
#ifdef CONFIG_TSB
uintptr_t base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH);
 
ASSERT(as->arch.tsb_description.tsb_base);
ASSERT(as->arch.itsb && as->arch.dtsb);
 
uintptr_t tsb = as->arch.tsb_description.tsb_base;
uintptr_t tsb = (uintptr_t) as->arch.itsb;
if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
/*
168,7 → 220,7
* by the locked 4M kernel DTLB entry. We need
* to demap the entry installed by as_install_arch().
*/
mmu_demap_page(tsb, 0, MMU_FLAG_DTLB);
dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, tsb);
}
#endif
}