* ========== Copyright Header Begin ==========================================
* OpenSPARC T2 Processor File: ncu.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 ============================================
* this is the niagara2 ncu module. the original source is taken from legion
* with minor/cosmetic modifications. The name of the relevent functions is
* kept same as in legion so as to allow easy updates.
* The original source has related CSRs, which are not needed for this
* module, but are still added(though incomplete in certain instances) in case
#include "cpu_interface.h"
static const char* piu_regions
[] = {"cfgio","mem32","mem64","piu_8mb","unknown"};
static int access_ncu(uint32_t cpuid
, void* obj
, uint64_t paddr
, mmi_bool_t wr
, uint32_t size
, uint64_t* buf
, uint8_t bytemask
);
int n2ncu_ui_cmd(void*, int argc
, char * argv
[]);
class n2Ncu
:public Module
{
#define MASK64( _high, _low ) ( ( (uint64_t)((~(uint64_t)0)>>(63-(_high))) ) & ( (uint64_t)( (~(uint64_t)0)<<(_low)) ) )
#define GETMASK64(x, hi, lo) (((uint64_t)(x) & MASK64((hi), (lo)))>>(lo))
/* src/procs/sunsparc/libniagara2/include/niagara2_device.h */
static const uint64_t NCU_CSR_BASE
= 0x8000000000;
static const uint64_t NCU_CSR_SIZE
= 0x100000000;
static const uint64_t PIU_MAX_REGION
= 4;
static const uint64_t NCU_REG_MASK
= 0x4ffff;
static const uint64_t NCU_TARGETS
= 64; /* number of virtual cores */
static const uint64_t NCU_DEV_MAX
= 128; /* max number of device Ids */
static const uint64_t NCU_DEV_ERR
= 1; /* device Id for ECC error */
static const uint64_t NCU_DEV_SSI
= 2; /* device Id for SSI interrupt */
static const uint64_t NCU_DEV_NIU_LB
= 64; /* device Id range for NIU interrupt */
static const uint64_t NCU_DEV_NIU_UB
= NCU_DEV_MAX
-1;
static const uint64_t NCU_MONDO_INT_MASK
= 0x40fff;
static const uint64_t NCU_MONDO_INT_BUSY
= MASK64(6,6);
static const uint64_t NCU_SOC_MASK
= MASK64(42,40)|MASK64(38,37)|MASK64(35,34)|MASK64(32,31)|MASK64(29,0);
static const uint64_t NCU_INT_MAN_MASK
= NCU_DEV_MAX
*8;
uint64_t NCU_INT_MAN_CPUID(uint64_t n
){ return ((n
&MASK64(13,8))>>8); }
static const uint64_t NCU_INT_ACK
= 0;
static const uint64_t NCU_INT_NACK
= -1;
static const uint64_t PIU_REGION_OFFSET_MASK
= MASK64(35,24);
static const uint64_t PIU_REGION_OFFSET_MASK_HI
= MASK64(39,36);
uint64_t int_man
[NCU_DEV_MAX
];
uint64_t l2_idx_hash_en_stat
;
uint64_t pcie_a_mem32_offset_base
;
uint64_t pcie_a_mem32_offset_mask
;
uint64_t pcie_a_mem64_offset_base
;
uint64_t pcie_a_mem64_offset_mask
;
uint64_t pcie_a_iocon_offset_base
;
uint64_t pcie_a_iocon_offset_mask
;
uint64_t soc_sii_err_syndrome
;
uint64_t soc_ncu_err_syndrome
;
uint64_t mondo_int_data0
[NCU_TARGETS
];
uint64_t mondo_int_data1
[NCU_TARGETS
];
uint64_t mondo_int_busy
[NCU_TARGETS
];
printf("base<%llx>size<%llx>mask<%llx>en<%d>\n",base
,size
,mask
,enable
);
CORE_AVAIL
= 0x01010,/* same as ASI_CORE_AVAILABLE */
BANK_ENABLE_STATUS
= 0x01028,
L2_IDX_HASH_EN
= 0x01030,
L2_IDX_HASH_EN_STATUS
= 0x01038,
PCIE_A_MEM32_OFFSET_BASE
= 0x02000,
PCIE_A_MEM32_OFFSET_MASK
= 0x02008,
PCIE_A_MEM64_OFFSET_BASE
= 0x02010,
PCIE_A_MEM64_OFFSET_MASK
= 0x02018,
PCIE_A_IOCON_OFFSET_BASE
= 0x02020,
PCIE_A_IOCON_OFFSET_MASK
= 0x02028,
SOC_LOG_ENABLE
= 0x03008,
SOC_INTERRUPT_ENABLE
= 0x03010,
SOC_ERROR_INJECTION
= 0x03018,
SOC_FATAL_ERROR_ENABLE
= 0x03020,
SOC_PENDING_ERROR_STATUS
= 0x03028,/* same as SOC_ESR */
SOC_SII_ERROR_SYNDROME
= 0x03030,
SOC_NCU_ERROR_SYNDROME
= 0x03038,
MONDO_INT_DATA0
= 0x40000,
MONDO_INT_DATA1
= 0x40200,
MONDO_INT_ADATA0
= 0x40400,
MONDO_INT_ADATA1
= 0x40600,
MONDO_INT_BUSY
= 0x40800,
MONDO_INT_ABUSY
= 0x40a00
* XXX need an interface to read asi registers from vonk to add support for
* ASI registers available through NCU
* a list of registers that will be dumped and restored by this module.
* in case more registers are added, or some offsets change or any
* incompatible change happens, and there exist dumps with old format that need to be
* supported, then create a new dumpRegsV2[]. The restore
* function should be able to differtiate and handle correctly the
* different versions. Otherwise just modify the V1 array and dump/restore
static const uint64_t dumpRegsV1
[25];
const char * current_dump_version
;
bool UINT64_RANGE_CHECK(uint64_t _low
, uint64_t _val
, uint64_t _high
){
return ((_val
- _low
) < (_high
- _low
));
void ASSIGN_NCU(uint64_t& _n
,uint64_t _m
,uint64_t val
, uint64_t offset
){
debug_err("%s: WARNING: attempt to write to reserved field in NCU\n"
" Write 0x%llx to register %s (offset %llx)\n",
getName(), val
, ncu_reg_name(offset
),offset
);
debug_more("%s: assigned %llx to register %s\n",getName(),val
,ncu_reg_name(offset
));
const char *ncu_reg_name(uint64_t reg
);
void niagara2_pcie_mapping(piu_region_t region
);
public: // external interface fns. that can be called by other modules/system
int access_regs(uint32_t cpuid
, uint64_t paddr
, mmi_bool_t wr
, uint32_t size
,\
uint64_t* buf
, uint8_t bytemask
);
const map_info_t
* getMap(piu_region_t region
){ return &map
[region
]; }
// send mondo to target strand. return either ACK = 0, or NACK = -1
int sendPiuMondo(VCPU_InterruptRequest
* r
){
extern Vcpu
*g_vcpu
[NCPU_MAX
];
debug_more("%s:sending interrupt to strand %x\n",getName(),r
->itid
);
int vector
= regs
.mondo_int_vec
& 0x3f;
int busy
= regs
.mondo_int_busy
[target
] >> 6 & 0x1;
regs
.mondo_int_data0
[target
] = r
->data
[0];
regs
.mondo_int_data1
[target
] = r
->data
[1];
regs
.mondo_int_busy
[target
] = 1 << 6;
Vcpu
*vcpu
= get_vcpu(target
);
int sendNiuMondo(VCPU_InterruptRequest
* r
){
extern Vcpu
*g_vcpu
[NCPU_MAX
];
int vector
= regs
.int_man
[r
->isid
] & 0x3f;
debug_more("%s:sending NIU interrupt tid:%x sid/ldg:%x vector:0x%x\n",getName(),r
->itid
, r
->isid
, vector
);
Vcpu
*vcpu
= get_vcpu(target
);
void handle_ui(int argc
, char * argv
[]);
printf("ui format: %s <command> <command args> ... \n",getName());
printf("%s supports following UI commands\n",getName());
printf(" dump [<filename>]\n\
dump the CSR contents to \'filename\' \n\
dump format is: <csr name> <csr offset> <csr value>\n");
printf(" restore <filename>\n\
restore the CSR contents from \'filename\' \n\
restore file format is same as dump file format\n");
printf(" debug [<level>]\n\
set the debug level for debug prints to \'level\'\n\
if \'level\' not provided, print current debug level\n\
public: // module interface
const char *get_help(){ return Module::get_help_string(); }
bool parse_arg(const char *){ return true; }
bool check_args(){return true; }
mmi_map_physio(NCU_CSR_BASE
,NCU_CSR_SIZE
,(void*)this,access_ncu
);
void module_added(mmi_instance_t
, const char*){ return; }
void module_deleted(mmi_instance_t
, const char*){ return; }
printf("%s: N2 NCU module\n"
"iomap base<%llx size<%llx>\n",getName(), NCU_CSR_BASE
,NCU_CSR_SIZE
);
printf("PCIE MAP -->\n");
for(int i
= 0; i
< 3; i
++){
printf("%s",piu_regions
[i
]);
void *get_interface(const char*){ return (void*)this; }
const char *get_version(){ return "1.0"; }
bool restore_v1(FILE *fp
);
n2Ncu(const char *_modname
, const char *_instance_name
);
map_info_t map
[PIU_MAX_REGION
];
pthread_mutex_t ncu_lock
;