* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: SS_Tte.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
* The above named 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 work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* ========== Copyright Header End ============================================
SS_Tte() : tte_is_real(0), tte_is_virt(0), usage_count(0), tte_flags(0) {}
// The first part of the SS_Tte object, the virt/phys_page/mask is for caching the TTE
// and applying fast matching (match()) and translation (trans()). All the TTE specifics
// should have been tested by the inst_mmu or data_mmu functions respectively in the strand.
// The adapt() function is used when the tag or taddr ( translated address) is updated.
bool match( SS_Vaddr a
) const { return (a
& virt_mask
) == virt_page
; }
SS_Paddr
trans( SS_Vaddr a
) const { return (a
&~ phys_mask
) | phys_page
; }
virt_mask
= ~SS_Vaddr(0) << (tte_page_size
* 3 + 13);
virt_page
= tte_tag
& virt_mask
;
phys_page
= tte_taddr
& virt_mask
;
SS_Tte
* next
; // Next pointer in the free tte list in the tlb class
uint_t index
; // The index in the TLB where this tte is located.
// The usage_count is 1 when the TTE is valid. Just before a TTE is demapped
// we set the usage_count to the number of strands that might use the TTE.
// When we are in tracing mode the usage_count is bumped to 2 and back to 1,
// this to prevent accidental cases where the TTE is being demapped and we
// we need it to produce trace output.
int_t usage_count
; // A count used to hold on to the TTE
// The third part of the TTE is the actual TTE information as per architecture.
// E.g all the associated bits.
PRIVILEGED
= 0x0001, // p
EXECUTABLE
= 0x0002, // x (ep)
NONFAULT
= 0x0008, // nfo
INV_ENDIAN
= 0x0010, // ie
SIDE_EFFECT
= 0x0080, // e
TAG_PARITY
= 0x0100, // tag parity
DATA_PARITY
= 0x0200, // data parity
MULTI_HIT
= 0x2000, // a condition that is set when TTE is looked up
VALID_ERROR
= 0x4000 // duplicated valid bit mismatch
int valid() { return tte_is_real
|| tte_is_virt
; }
int is_real() { return tte_is_real
; }
int is_virt() { return tte_is_virt
; }
uint8_t pid() { return tte_pid
; }
uint16_t context() { return tte_context
; }
uint8_t page_size() { return tte_page_size
; }
SS_Vaddr
tag() { return tte_tag
; }
SS_Paddr
taddr() { return tte_taddr
; }
void assign_flag( Flags bit
, int val
) { if (val
) tte_flags
|= bit
; else tte_flags
&= ~bit
; }
int test_flag( Flags bit
) { return 0 != (tte_flags
& bit
); }
int p() { return test_flag(PRIVILEGED
); }
int x() { return test_flag(EXECUTABLE
); }
int w() { return test_flag(WRITEABLE
); }
int nfo() { return test_flag(NONFAULT
); }
int ie() { return test_flag(INV_ENDIAN
); }
int cp() { return test_flag(CP
); }
int cv() { return test_flag(CV
); }
int e() { return test_flag(SIDE_EFFECT
); }
int lock() { return test_flag(LOCK_BIT
); }
int valid_bit() { return test_flag(VALID_BIT
); }
int real_bit() { return test_flag(REAL_BIT
); }
int multi_hit() { return test_flag(MULTI_HIT
); }
int tag_parity_error() { return test_flag(TAG_PARITY
); }
int data_parity_error() { return test_flag(DATA_PARITY
); }
int valid_bit_error() { return test_flag(VALID_ERROR
); }
void p( int f
) { assign_flag(PRIVILEGED
,f
); }
void x( int f
) { assign_flag(EXECUTABLE
,f
); }
void w( int f
) { assign_flag(WRITEABLE
,f
); }
void nfo( int f
) { assign_flag(NONFAULT
,f
); }
void ie( int f
) { assign_flag(INV_ENDIAN
,f
); }
void cp( int f
) { assign_flag(CP
,f
); }
void cv( int f
) { assign_flag(CV
,f
); }
void e( int f
) { assign_flag(SIDE_EFFECT
,f
); }
void lock( int f
) { assign_flag(LOCK_BIT
,f
); }
void valid_bit( int f
) { assign_flag(VALID_BIT
,f
); virt_real_update(); }
void real_bit( int f
) { assign_flag(REAL_BIT
,f
); virt_real_update(); }
void multi_hit( int f
) { assign_flag(MULTI_HIT
,f
); }
void tag_parity_error( int f
) { assign_flag(TAG_PARITY
,f
); }
void data_parity_error( int f
) { assign_flag(DATA_PARITY
,f
); }
void valid_bit_error( int f
) { assign_flag(VALID_ERROR
,f
); }
// We keep two one hot bits for faster checking for
// valid real or valid virt TTEs. However for interface reasons
// we need to keep the valid and real bit as is. Just internally
// we use the one bit test is_real, is_virt flags.
void virt( int v
) { tte_is_virt
= v
; }
void real( int r
) { tte_is_real
= r
; }
void pid( uint8_t p
) { tte_pid
= p
; }
void context( uint16_t c
) { tte_context
= c
; }
void page_size( uint8_t p
) { tte_page_size
= p
; adapt(); }
void tag( SS_Vaddr t
) { tte_tag
= t
; adapt(); }
void taddr( SS_Paddr t
) { tte_taddr
= t
; adapt(); }
void set_real( uint16_t pid
, uint8_t ps
, SS_Vaddr tag
, SS_Paddr dst
)
void set_virt( uint16_t pid
, uint16_t context
, uint8_t ps
, SS_Vaddr tag
, SS_Paddr dst
)
bool match_real( SS_Vaddr ra
, uint_t pid
) const
return tte_is_real
&& match(ra
) && (tte_pid
== pid
);
bool match_virt( SS_Vaddr va
, uint64_t ctxt
, uint_t pid
) const
return tte_is_virt
&& (tte_context
== ctxt
) && match(va
) && (tte_pid
== pid
);
bool match_virt( SS_Vaddr va
, uint64_t ctxt0
, uint64_t ctxt1
, uint_t pid
) const
return tte_is_virt
&& ((tte_context
== ctxt0
) || (tte_context
== ctxt1
)) && match(va
) && (tte_pid
== pid
);
// This routine checks if there is a multi hit error or a tag parity error or data parity error
return multi_hit() | tag_parity_error() | data_parity_error() | valid_bit_error();
// insert_tsb_tte() inserts a sun4v TTE into this TTE. The vpn of the TTE is extended
// with bits 21:13 of the va, as the vpn in the TSB only has bit 63:22.
void insert_tsb_tte( uint16_t pid
, uint64_t tag
, uint64_t data
, SS_Vaddr addr
)
tte_context
= tsb_tag
.context();
tte_page_size
= tsb_data
.size();
tte_tag
= ((tsb_tag
.va() << 9) | ((addr
>> 13) & 0x1ff)) << 13;
tte_taddr
= tsb_data
.pa() << 13;
// insert_sun4u_tsb_tte() inserts a sun4u TTE into the TTE. The vpn of the TTE is extended
// with bits 21:13 of the va, as the vpn in the TSB only has bit 63:22.
void insert_sun4u_tsb_tte( uint16_t pid
, uint64_t tag
, uint64_t data
, SS_Vaddr addr
)
// TODO for Ch and N1, see above
void snapshot( SS_SnapShot
& ss
, const char* prefix
);
void dump(FILE *fp
=stdout
);
uint8_t tte_is_real
; // Nonzero for valid real TTE
uint8_t tte_is_virt
; // Nonzero for valid virt TTE
uint8_t tte_pid
; // The partition for which this TTE is valid
uint8_t tte_page_size
; // 0=8Kb, 1=64Kb, ...
uint16_t tte_context
; // The context for virt TTE
uint16_t tte_flags
; // The flags p,w,x,ie,nfo ...
SS_Vaddr tte_tag
; // The TTE tag (va or ra)
SS_Paddr tte_taddr
; // The TTE target address (pa or ra)