source: trunk/hal/tsar_mips32/drivers/soclib_pic.c @ 432

Last change on this file since 432 was 432, checked in by alain, 4 years ago

bloup

File size: 20.2 KB
Line 
1/*
2 * soclib_pic.c - soclib PIC driver implementation.
3 *
4 * Author  Alain Greiner (2016,2017)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_types.h>
25#include <chdev.h>
26#include <soclib_pic.h>
27#include <errno.h>
28#include <string.h>
29#include <vfs.h>
30#include <rpc.h>
31#include <cluster.h>
32#include <printk.h>
33#include <core.h>
34#include <thread.h>
35
36//////////////////////////////////////////////////////////////////////////////////////
37//         Extern variables
38//////////////////////////////////////////////////////////////////////////////////////
39
40extern  chdev_directory_t chdev_dir;    // defined in chdev.h / allocated in kerneL-init.c
41
42extern  iopic_input_t  iopic_input;  // defined in dev_pic.h / allocated in kernel_init.c
43extern  lapic_input_t  lapic_input;  // defined in dev_pic.h / allocated in kernel_init.c
44 
45
46
47//////////////////////////////////////////////////////////////////////////////////////
48//        SOCLIB PIC private functions
49//////////////////////////////////////////////////////////////////////////////////////
50
51///////////////////////////////
52uint32_t soclib_pic_wti_alloc()
53{
54    uint32_t index;
55
56    // get pointer on cluster extension for SOCLIB PIC (XCU descriptor)
57    soclib_pic_cluster_t * ext_ptr = LOCAL_CLUSTER->pic_extend;
58
59    assert( (ext_ptr->first_free_wti < ext_ptr->wti_nr) , __FUNCTION__ ,
60            "no free WTI found : too much external IRQs\n");
61
62    // update WTI allocator
63    index = ext_ptr->first_free_wti;
64    ext_ptr->first_free_wti++;
65
66    return index;
67
68}  // end soclib_pic_wti_alloc()
69
70///////////////////////////////////////
71inline uint32_t * soclib_pic_xcu_base()
72{
73    return ((soclib_pic_cluster_t *)(LOCAL_CLUSTER->pic_extend))->xcu_base;
74}
75
76/////////////////////////////////////////////////////////
77inline uint32_t * soclib_pic_remote_xcu_base( cxy_t cxy )
78{
79    soclib_pic_cluster_t * extend;
80
81    // get extended pointer on PIC extension in remote cluster
82    extend = hal_remote_lpt( XPTR( cxy , &cluster_manager.pic_extend ) );
83
84        return (uint32_t *)hal_remote_lpt( XPTR( cxy , &extend->xcu_base ) );
85                 
86}
87
88///////////////////////////////////////////
89void soclib_pic_xcu_status( lid_t      lid,
90                            uint32_t * hwi_status,
91                            uint32_t * wti_status,
92                            uint32_t * pti_status )
93{
94    // get local XCU segment base
95        uint32_t * base = soclib_pic_xcu_base();
96
97    // read PRIO register
98    // in TSAR : XCU output [4*lid] is connected to core [lid]
99        uint32_t prio = base[ (XCU_PRIO << 5) | (lid<<2) ];
100
101    *wti_status = (prio & 0x4) ? (((prio >> 24) & 0x1F) + 1) : 0;
102    *hwi_status = (prio & 0x2) ? (((prio >> 16) & 0x1F) + 1) : 0;
103    *pti_status = (prio & 0x1) ? (((prio >>  8) & 0x1F) + 1) : 0;
104
105}
106
107////////////////////////////////////////////////////
108inline uint32_t soclib_pic_xcu_ack( uint32_t * reg )
109{
110    return *reg;
111}
112
113/////////////////////////////
114void soclib_pic_irq_handler()
115{
116    uint32_t   hwi_status;   // HWI index + 1  / no pending HWI if 0
117    uint32_t   wti_status;   // WTI index + 1  / no pending WTI if 0
118    uint32_t   pti_status;   // PTI index + 1  / no pending PTI if 0
119    chdev_t  * src_chdev;    // pointer on source chdev descriptor
120    uint32_t   index;        // WTI / HWI / PTI index
121
122    uint32_t * xcu_base = soclib_pic_xcu_base();
123
124    core_t   * core = CURRENT_THREAD->core;
125
126    // get XCU status
127    soclib_pic_xcu_status( core->lid,
128                           &hwi_status,
129                           &wti_status,
130                           &pti_status );
131
132    irq_dmsg("\n[DBG] %s : core[%x,%d] enter / WTI = %x / HWI = %x / PTI = %x\n",
133             __FUNCTION__ , local_cxy , core->lid , wti_status , hwi_status , pti_status );
134
135    // analyse status and handle up to 3 pending IRQ (one WTI, one HWI, one PTI)
136
137    if( wti_status )          // pending WTI
138        {
139        index = wti_status - 1;
140
141        if( index < LOCAL_CLUSTER->cores_nr )   // it is an IPI
142        {
143            assert( (index == core->lid) , __FUNCTION__ , "illegal IPI index" );
144
145            irq_dmsg("\n[DBG] %s : core[%x,%d] received an IPI / cycle %d\n",
146             __FUNCTION__ , local_cxy , core->lid , hal_time_stamp() );
147
148            // acknowledge WTI (this require an XCU read)
149            uint32_t   ack  = xcu_base[(XCU_WTI_REG << 5) | core->lid];
150           
151            // check RPC FIFO,  and activate or create a RPC thread
152            // condition is always true, but we must use the ack value
153            if( ack + 1 ) rpc_check();
154        }
155        else                                    // it is an external device
156        {
157            // get pointer on source chdev
158            src_chdev = ((soclib_pic_core_t *)core->pic_extend)->wti_vector[index];
159
160                    if( src_chdev == NULL )        // strange, but not fatal
161                    {
162                printk("\n[WARNING] in %s : no handler for WTI %d on core %d in cluster %x\n",
163                       __FUNCTION__ , index , core->lid , local_cxy );
164
165                    core->spurious_irqs ++;
166
167                // disable WTI in local XCU controller
168                uint32_t * base = soclib_pic_xcu_base();
169                base[(XCU_MSK_WTI_DISABLE << 5) | core->lid] = 1 << core->lid;
170            }
171            else                                 // call relevant ISR
172            {
173                irq_dmsg("\n[DBG] %s : core[%x,%d] received external WTI %d / cycle %d\n",
174                __FUNCTION__ , local_cxy , core->lid , index , hal_time_stamp() );
175
176                // call ISR
177                    src_chdev->isr( src_chdev );
178            }
179        }
180        }
181
182        if( hwi_status )      // pending HWI
183        {
184        index = hwi_status - 1;
185
186        // get pointer on source chdev
187        src_chdev = ((soclib_pic_core_t *)core->pic_extend)->hwi_vector[index];
188
189                if( src_chdev == NULL )        // strange, but not fatal
190                {
191            printk("\n[WARNING] in %s : no handler for HWI %d on core %d in cluster %x\n",
192                   __FUNCTION__ , index , core->lid , local_cxy );
193
194                core->spurious_irqs ++;
195
196            // disable HWI in local XCU controller
197            xcu_base[(XCU_MSK_HWI_DISABLE << 5) | core->lid] = 1 << core->lid;
198                }
199        else                    // call relevant ISR
200        {
201            irq_dmsg("\n[DBG] %s : core[%x,%d] received HWI %d / cycle %d\n",
202            __FUNCTION__ , local_cxy , core->lid , index , hal_time_stamp() );
203
204            // call ISR
205                    src_chdev->isr( src_chdev );
206        }
207        }
208
209    if( pti_status )      // pending PTI
210        {
211        index = pti_status - 1;
212
213        irq_dmsg("\n[DBG] %s : core[%x,%d] received PTI %d / cycle %d\n",
214        __FUNCTION__ , core->lid , local_cxy , index , hal_time_stamp() );
215
216        assert( (index == core->lid) , __FUNCTION__ , "unconsistent PTI index\n");
217
218        // acknowledge PTI (this require a read access to XCU)
219        uint32_t   ack  = xcu_base[(XCU_PTI_ACK << 5) | core->lid];
220
221        // execute all actions related to TICK event
222        // condition is always true, but we must use the ack value
223        if( ack + 1 ) core_clock( core );
224        }
225}  // end soclib_pic_irq_handler()
226
227
228
229
230//////////////////////////////////////////////////////////////////////////////////////
231//         SOCLIC PIC device  generic API
232//////////////////////////////////////////////////////////////////////////////////////
233
234/////////////////////////////////////
235void soclib_pic_init( chdev_t * pic )
236{
237    uint32_t    i;      // for loop on IOPIC inputs
238    uint32_t    x;      // for loop on clusters in a row
239    uint32_t    y;      // for loop on clusters in a column inputs
240    uint32_t    lid;    // for loop on cores in a cluster
241
242    // get target architecture parameters
243    cluster_t * cluster = LOCAL_CLUSTER;
244    uint32_t    x_size  = cluster->x_size;
245    uint32_t    y_size  = cluster->y_size;
246    uint32_t    y_width = cluster->y_width;
247    uint32_t    ncores  = cluster->cores_nr;
248
249    // get IOPIC controller cluster and segment base pointer
250    cxy_t      iopic_seg_cxy = (cxy_t)GET_CXY( pic->base );
251    uint32_t * iopic_seg_ptr = (uint32_t *)GET_PTR( pic->base );
252
253    // reset the IOPIC component registers : disable all input IRQs
254    for( i = 0 ; i < CONFIG_MAX_EXTERNAL_IRQS ; i++ )
255    {
256        xptr_t iopic_seg_xp = XPTR( iopic_seg_cxy,
257                                    iopic_seg_ptr + i*IOPIC_SPAN + IOPIC_MASK ); 
258        hal_remote_sw( iopic_seg_xp , 0 ); 
259    }
260   
261    // GET XCU controller segment base
262    uint32_t * base = soclib_pic_xcu_base();
263
264    // reset the XCU component registers in all clusters:
265    // mask all HWIs, all WTIs, and all PTIs, for all cores   
266    for( x = 0 ; x < x_size ; x++ )
267    {
268        for( y = 0 ; y < y_size ; y++ )
269        {
270            for( lid = 0 ; lid < ncores ; lid++ )
271            {
272                cxy_t cxy = (x<<y_width) + y;
273                xptr_t hwi_mask_xp = XPTR( cxy , base + (XCU_MSK_HWI_DISABLE << 5 | lid) );
274                xptr_t wti_mask_xp = XPTR( cxy , base + (XCU_MSK_WTI_DISABLE << 5 | lid) );
275                xptr_t pti_mask_xp = XPTR( cxy , base + (XCU_MSK_PTI_DISABLE << 5 | lid) );
276                hal_remote_sw( hwi_mask_xp , 0xFFFFFFFF );
277                hal_remote_sw( wti_mask_xp , 0xFFFFFFFF );
278                hal_remote_sw( pti_mask_xp , 0xFFFFFFFF );
279            }
280        }
281    }
282}  // end soclib_pic_init()
283
284//////////////////////////////////////////////////
285void soclib_pic_extend_init( uint32_t * xcu_base )
286{
287    soclib_pic_cluster_t * cluster_ext_ptr;   
288    soclib_pic_core_t    * core_ext_ptr;
289    kmem_req_t             req;
290    uint32_t               lid;
291    uint32_t               idx;
292
293    cluster_t            * cluster = LOCAL_CLUSTER;
294
295    // create core extension for all cores in cluster
296    for( lid = 0 ; lid < cluster->cores_nr ; lid++ )
297    {
298        // allocate memory for core extension
299        req.type     = KMEM_GENERIC;
300        req.size     = sizeof(soclib_pic_core_t);
301        req.flags    = AF_KERNEL;
302        core_ext_ptr = kmem_alloc( &req );
303
304        assert( (core_ext_ptr != NULL) , __FUNCTION__ ,
305                "cannot allocate memory for core extension\n");
306   
307        // reset the HWI / WTI  interrupt vectors
308        for( idx = 0 ; idx < SOCLIB_MAX_HWI ; idx++ ) core_ext_ptr->hwi_vector[idx] = NULL;
309        for( idx = 0 ; idx < SOCLIB_MAX_WTI ; idx++ ) core_ext_ptr->wti_vector[idx] = NULL;
310
311        // register PIC extension in core descriptor
312        cluster->core_tbl[lid].pic_extend = core_ext_ptr;
313    }
314
315    // allocate memory for cluster extension
316    req.type        = KMEM_GENERIC;
317    req.size        = sizeof(soclib_pic_cluster_t);
318    req.flags       = AF_KERNEL;
319    cluster_ext_ptr = kmem_alloc( &req );
320
321    assert( (cluster_ext_ptr != NULL) , __FUNCTION__ ,
322            "cannot allocate memory for cluster extension\n");
323
324    // get XCU characteristics from the XCU config register
325    uint32_t  config = xcu_base[XCU_CONFIG<<5];
326    uint32_t  wti_nr = (config >> 16) & 0xFF; 
327    uint32_t  hwi_nr = (config >> 8 ) & 0xFF; 
328    uint32_t  pti_nr = (config      ) & 0xFF; 
329
330    // initialize the cluster extension
331    // The first WTI slots are for IPIs (one slot per core)
332    cluster_ext_ptr->xcu_base       = xcu_base;
333    cluster_ext_ptr->hwi_nr         = hwi_nr;
334    cluster_ext_ptr->wti_nr         = wti_nr;
335    cluster_ext_ptr->pti_nr         = pti_nr;
336    cluster_ext_ptr->first_free_wti = cluster->cores_nr;
337
338    // register PIC extension in cluster manager
339    cluster->pic_extend = cluster_ext_ptr;
340
341}  // end soclib_pic_extend_init()
342
343////////////////////////////////////////
344void soclib_pic_bind_irq( lid_t     lid,
345                          chdev_t * src_chdev )
346{
347    // get extended & local pointers on PIC chdev descriptor
348    xptr_t     pic_xp  = chdev_dir.pic;
349    cxy_t      pic_cxy = GET_CXY( pic_xp );
350    chdev_t *  pic_ptr = (chdev_t *)GET_PTR( pic_xp );
351
352    // get extended and local pointers on IOPIC  segment base
353    xptr_t     seg_pic_xp  = hal_remote_lwd( XPTR( pic_cxy , &pic_ptr->base ) );
354    cxy_t      seg_pic_cxy = GET_CXY( seg_pic_xp );
355    uint32_t * seg_pic_ptr = (uint32_t *)GET_PTR( seg_pic_xp );
356
357    // get local pointer on XCU segment base
358    uint32_t * seg_xcu_ptr = soclib_pic_xcu_base();
359
360    // get the source chdev functionnal type, channel, and direction
361    uint32_t func    = src_chdev->func;
362    uint32_t channel = src_chdev->channel;
363    bool_t   is_rx   = src_chdev->is_rx;
364
365    if( (func == DEV_FUNC_IOC) || (func == DEV_FUNC_NIC) ||
366        (func == DEV_FUNC_TXT) || (func == DEV_FUNC_IOB) )          // external IRQ => WTI
367    {
368        // get external IRQ index
369        uint32_t  hwi_id;   
370        if     (  func == DEV_FUNC_IOC            ) hwi_id = iopic_input.ioc[channel];
371        else if(  func == DEV_FUNC_TXT  &&  is_rx ) hwi_id = iopic_input.txt_rx[channel];
372        else if(  func == DEV_FUNC_TXT  && !is_rx ) hwi_id = iopic_input.txt_tx[channel];
373        else if( (func == DEV_FUNC_NIC) &&  is_rx ) hwi_id = iopic_input.nic_rx[channel];
374        else if( (func == DEV_FUNC_NIC) && !is_rx ) hwi_id = iopic_input.nic_tx[channel];
375        else if(  func == DEV_FUNC_IOB            ) hwi_id = iopic_input.iob;
376        else      assert( false , __FUNCTION__ , "illegal device functionnal type\n");
377
378        // get a WTI mailbox from local XCU descriptor 
379        uint32_t wti_id = soclib_pic_wti_alloc();
380
381        // register IRQ type and index in chdev
382        src_chdev->irq_type = SOCLIB_TYPE_WTI;
383        src_chdev->irq_id   = wti_id;
384
385        // compute extended pointer on WTI mailbox in local XCU
386        xptr_t wti_xp = XPTR( local_cxy , &seg_xcu_ptr[(XCU_WTI_REG << 5) | wti_id] );
387
388            // set the IOPIC_ADDRESS and IOPIC_EXTEND registers in IOPIC
389        uint32_t lsb_wdata = (uint32_t)wti_xp;
390        uint32_t msb_wdata = (uint32_t)(wti_xp >> 32);
391        xptr_t   lsb_xp = XPTR( seg_pic_cxy , seg_pic_ptr+hwi_id*IOPIC_SPAN+IOPIC_ADDRESS );
392        xptr_t   msb_xp = XPTR( seg_pic_cxy , seg_pic_ptr+hwi_id*IOPIC_SPAN+IOPIC_EXTEND );
393        hal_remote_sw( lsb_xp , lsb_wdata );
394        hal_remote_sw( msb_xp , msb_wdata );
395
396        // enable IRQ in IOPIC
397        hal_remote_sw( XPTR( seg_pic_cxy , seg_pic_ptr+hwi_id*IOPIC_SPAN+IOPIC_MASK ), 1 );
398
399        // update the WTI interrupt vector for core[lid]
400        core_t * core = &LOCAL_CLUSTER->core_tbl[lid];
401        ((soclib_pic_core_t *)core->pic_extend)->wti_vector[wti_id] = src_chdev;
402
403pic_dmsg("\n[DBG] %s : %s / channel = %d / rx = %d / hwi_id = %d / wti_id = %d / cluster = %x\n",
404__FUNCTION__ , chdev_func_str( func ) , channel , is_rx , hwi_id , wti_id , local_cxy );
405
406    }
407    else if( (func == DEV_FUNC_DMA) || (func == DEV_FUNC_MMC) )   // internal IRQ => HWI
408    {
409        // get internal IRQ index
410        uint32_t hwi_id;
411        if( func == DEV_FUNC_DMA ) hwi_id = lapic_input.dma[channel];
412        else                       hwi_id = lapic_input.mmc;
413
414        // register IRQ type and index in chdev
415        src_chdev->irq_type = SOCLIB_TYPE_HWI;
416        src_chdev->irq_id   = hwi_id;
417
418        // update the HWI interrupt vector for core[lid]
419        core_t * core = &LOCAL_CLUSTER->core_tbl[lid];
420        ((soclib_pic_core_t *)core->pic_extend)->wti_vector[hwi_id] = src_chdev;
421
422pic_dmsg("\n[DBG] %s : %s / channel = %d / hwi_id = %d / cluster = %x\n",
423__FUNCTION__ , chdev_func_str( func ) , channel , hwi_id , local_cxy );
424
425    }
426    else
427    {
428        assert( false , __FUNCTION__ , "illegal device functionnal type\n" );
429    } 
430}  // end soclib_pic_bind_irq();
431
432///////////////////////////////////////
433void soclib_pic_enable_irq( lid_t  lid,
434                            xptr_t src_chdev_xp )
435{
436    // get cluster and local pointer on remote src_chdev
437    cxy_t     src_chdev_cxy = GET_CXY( src_chdev_xp );
438    chdev_t * src_chdev_ptr = (chdev_t *)GET_PTR( src_chdev_xp );
439
440    // get local pointer on remote XCU segment base
441    uint32_t * seg_xcu_ptr = soclib_pic_remote_xcu_base( src_chdev_cxy );
442
443    // get the source chdev IRQ type and index
444    uint32_t irq_type = hal_remote_lw( XPTR( src_chdev_cxy , &src_chdev_ptr->irq_type ) );
445    uint32_t irq_id   = hal_remote_lw( XPTR( src_chdev_cxy , &src_chdev_ptr->irq_id ) );
446
447    if( irq_type == SOCLIB_TYPE_HWI )
448    {
449        // enable this HWI in remote XCU controller
450        // in TSAR : XCU output [4*lid] is connected to core [lid]
451        hal_remote_sw( XPTR( src_chdev_cxy , 
452                       &seg_xcu_ptr[ (XCU_MSK_HWI_ENABLE << 5) | (lid<<4) ] ) , (1 << irq_id) );
453    }
454    else if( irq_type == SOCLIB_TYPE_WTI )
455    {
456        // enable this WTI in remote XCU controller
457        // in TSAR : XCU output [4*lid] is connected to core [lid]
458        hal_remote_sw( XPTR( src_chdev_cxy , 
459                       &seg_xcu_ptr[ (XCU_MSK_WTI_ENABLE << 5) | (lid<<4) ] ) , (1 << irq_id) );
460    }
461    else
462    {
463        assert( false , __FUNCTION__ , "illegal IRQ type\n" );
464    }
465} // end soclib_pic_enable_irq()
466
467////////////////////////////////////////
468void soclib_pic_disable_irq( lid_t  lid,
469                             xptr_t src_chdev_xp )
470{
471    // get cluster and local pointer on remote src_chdev
472    cxy_t     src_chdev_cxy = GET_CXY( src_chdev_xp );
473    chdev_t * src_chdev_ptr = (chdev_t *)GET_PTR( src_chdev_xp );
474
475    // get local pointer on remote XCU segment base
476    uint32_t * seg_xcu_ptr = soclib_pic_remote_xcu_base( src_chdev_cxy );
477
478    // get the source chdev IRQ type and index
479    uint32_t irq_type = hal_remote_lw( XPTR( src_chdev_cxy , &src_chdev_ptr->irq_type ) );
480    uint32_t irq_id   = hal_remote_lw( XPTR( src_chdev_cxy , &src_chdev_ptr->irq_id ) );
481
482    if( irq_type == SOCLIB_TYPE_HWI )
483    {
484        // enable this HWI in remote XCU controller
485        // in TSAR : XCU output [4*lid] is connected to core [lid]
486        hal_remote_sw( XPTR( src_chdev_cxy , 
487                       &seg_xcu_ptr[(XCU_MSK_HWI_DISABLE << 5) | (lid<<2) ] ) , (1 << irq_id) );
488    }
489    else if( irq_type == SOCLIB_TYPE_WTI )
490    {
491        // enable this WTI in remote XCU controller
492        // in TSAR : XCU output [4*lid] is connected to core [lid]
493        hal_remote_sw( XPTR( src_chdev_cxy , 
494                       &seg_xcu_ptr[(XCU_MSK_WTI_DISABLE << 5) | (lid<<4) ] ) , (1 << irq_id) );
495    }
496    else
497    {
498        assert( false , __FUNCTION__ , "illegal IRQ type\n" );
499    }
500} // end soclib_pic_enable_irq()
501
502///////////////////////////////////////////////
503void soclib_pic_enable_timer( uint32_t period )
504{
505    // calling core local index
506    lid_t  lid = CURRENT_CORE->lid;
507
508    // get XCU segment base
509    uint32_t * base = soclib_pic_xcu_base();
510
511    // set period value in XCU (in cycles)
512    uint32_t cycles = period * SOCLIB_CYCLES_PER_MS;
513    base[(XCU_PTI_PER << 5) | lid] = cycles;
514
515    // enable PTI in local XCU controller
516    // In TSAR : XCU output [4*lid] is connected to core [lid]
517    base[ (XCU_MSK_PTI_ENABLE << 5) | (lid<<2) ] = 1 << lid;
518}
519
520////////////////////////////
521void soclib_pic_enable_ipi()
522{
523    // calling core local index
524    lid_t  lid = CURRENT_CORE->lid;
525
526    // get XCU segment base
527    uint32_t * base = soclib_pic_xcu_base();
528
529    // enable WTI in local XCU controller
530    // In TSAR : XCU output [4*lid] is connected to core [lid]
531    base[ (XCU_MSK_WTI_ENABLE << 5) | (lid<<2) ] = 1 << lid;
532}
533
534///////////////////////////////////////
535void soclib_pic_send_ipi( cxy_t    cxy,
536                          lid_t    lid )
537{
538    // get pointer on local XCU segment base
539    uint32_t * base = soclib_pic_xcu_base();
540
541    // write to WTI mailbox[cxy][lid]
542    hal_remote_sw( XPTR( cxy , &base[(XCU_WTI_REG << 5) | lid ] ) , 0 );
543}
544
545/////////////////////////
546void soclib_pic_ack_ipi()
547{
548    // get calling core local index
549    lid_t      lid  = CURRENT_THREAD->core->lid;
550
551    // get pointer on local XCU segment base
552    uint32_t * base = soclib_pic_xcu_base();
553
554    // acknowlege IPI
555    uint32_t   ack  = base[ (XCU_WTI_REG << 5) | lid ];
556
557    // we must make a fake use for ack value to avoid a warning
558    if( (ack + 1) == 0 ) asm volatile( "nop" );
559}
560   
561
Note: See TracBrowser for help on using the repository browser.