@ -84,28 +84,6 @@ static uint8_t pnv_xive_block_id(PnvXive *xive)
return blk ;
}
/*
* Remote access to controllers . HW uses MMIOs . For now , a simple scan
* of the chips is good enough .
*
* TODO : Block scope support
*/
static PnvXive * pnv_xive_get_remote ( uint8_t blk )
{
PnvMachineState * pnv = PNV_MACHINE ( qdev_get_machine ( ) ) ;
int i ;
for ( i = 0 ; i < pnv - > num_chips ; i + + ) {
Pnv9Chip * chip9 = PNV9_CHIP ( pnv - > chips [ i ] ) ;
PnvXive * xive = & chip9 - > xive ;
if ( pnv_xive_block_id ( xive ) = = blk ) {
return xive ;
}
}
return NULL ;
}
/*
* VST accessors for SBE , EAT , ENDT , NVT
*
@ -209,6 +187,42 @@ static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type,
return pnv_xive_vst_addr_direct ( xive , type , vsd , ( idx % vst_per_page ) ) ;
}
/*
* This is a simplified model of operation forwarding on a remote IC .
*
* A PC MMIO address is built to identify the NVT structure . The load
* on the remote IC will return the address of the structure in RAM ,
* which will then be used by pnv_xive_vst_write / read to perform the
* RAM operation .
*/
static uint64_t pnv_xive_vst_addr_remote ( PnvXive * xive , uint32_t type ,
uint64_t vsd , uint8_t blk ,
uint32_t idx )
{
const XiveVstInfo * info = & vst_infos [ type ] ;
uint64_t remote_addr = vsd & VSD_ADDRESS_MASK ;
uint64_t vst_addr ;
MemTxResult result ;
if ( type ! = VST_TSEL_VPDT ) {
xive_error ( xive , " VST: invalid access on remote VST %s %x/%x !? " ,
info - > name , blk , idx ) ;
return 0 ;
}
remote_addr | = idx < < xive - > pc_shift ;
vst_addr = address_space_ldq_be ( & address_space_memory , remote_addr ,
MEMTXATTRS_UNSPECIFIED , & result ) ;
if ( result ! = MEMTX_OK ) {
xive_error ( xive , " VST: read failed at @0x% " HWADDR_PRIx
" for NVT %x/%x \n " , remote_addr , blk , idx ) ;
return 0 ;
}
return vst_addr ;
}
static uint64_t pnv_xive_vst_addr ( PnvXive * xive , uint32_t type , uint8_t blk ,
uint32_t idx )
{
@ -225,14 +239,7 @@ static uint64_t pnv_xive_vst_addr(PnvXive *xive, uint32_t type, uint8_t blk,
/* Remote VST access */
if ( GETFIELD ( VSD_MODE , vsd ) = = VSD_MODE_FORWARD ) {
if ( type ! = VST_TSEL_VPDT ) {
xive_error ( xive , " VST: invalid access on remote VST %s %x/%x !? " ,
info - > name , blk , idx ) ;
return 0 ;
}
xive = pnv_xive_get_remote ( blk ) ;
return xive ? pnv_xive_vst_addr ( xive , type , blk , idx ) : 0 ;
return pnv_xive_vst_addr_remote ( xive , type , vsd , blk , idx ) ;
}
if ( VSD_INDIRECT & vsd ) {
@ -1785,16 +1792,20 @@ static const MemoryRegionOps pnv_xive_vc_ops = {
} ;
/*
* Presenter Controller MMIO region . The Virtualization Controller
* updates the IPB in the NVT table when required . Not modeled .
* Presenter Controller MMIO region . Points to the NVT sets .
*
* HW implements all possible mem ops to the underlying NVT structure
* but QEMU does not need to be so precise . The model implementation
* simply returns the RAM address of the NVT structure which is then
* used by pnv_xive_vst_write / read to perform the RAM operation .
*/
static uint64_t pnv_xive_pc_read ( void * opaque , hwaddr addr ,
unsigned size )
static uint64_t pnv_xive_pc_read ( void * opaque , hwaddr offset , unsigned size )
{
PnvXive * xive = PNV_XIVE ( opaque ) ;
uint32_t nvt_idx = offset > > xive - > pc_shift ;
uint8_t blk = pnv_xive_block_id ( xive ) ; /* TODO: VDT -> block xlate */
xive_error ( xive , " PC: invalid read @% " HWADDR_PRIx , addr ) ;
return - 1 ;
return pnv_xive_vst_addr ( xive , VST_TSEL_VPDT , blk , nvt_idx ) ;
}
static void pnv_xive_pc_write ( void * opaque , hwaddr addr ,
@ -2016,6 +2027,7 @@ static void pnv_xive_realize(DeviceState *dev, Error **errp)
/* Presenter Controller MMIO region (not modeled) */
memory_region_init_io ( & xive - > pc_mmio , OBJECT ( xive ) , & pnv_xive_pc_ops , xive ,
" xive-pc " , PNV9_XIVE_PC_SIZE ) ;
xive - > pc_mmio . disable_reentrancy_guard = true ;
/* Thread Interrupt Management Area (Direct) */
memory_region_init_io ( & xive - > tm_mmio , OBJECT ( xive ) , & pnv_xive_tm_ops ,