source: soft/giet_vm/giet_drivers/ioc_driver.c @ 313

Last change on this file since 313 was 313, checked in by alain, 11 years ago

The main modif is in TTY driver: The hard lock implemented in the
vci_multi_tty component is not used anymore, because this (non cacheable)
lock was not scalable... It has been replaced by a software (cacheable) lock
that has a better scalability in case of hardware cache coherence.
(see the _tty_get_lock() and _tty_release_lock() functions)

File size: 16.3 KB
RevLine 
[258]1///////////////////////////////////////////////////////////////////////////////////
[289]2// File       : ioc_driver.c
3// Date       : 23/05/2013
4// Author     : alain greiner
5// Maintainer : cesar fuguet
[258]6// Copyright (c) UPMC-LIP6
7///////////////////////////////////////////////////////////////////////////////////
8// The ioc_driver.c and ioc_driver.h files are part ot the GIET-VM kernel.
9//
[295]10// This abstact driver define a generic API, supporting various physical
11// block device controlers, including:
12// - vci_block_device : single channel)                    => bdv_driver
13// - vci_ahci         : multi channels                     => hba_driver
14// - sd_card          : single channel                     => sdc_driver
15// - ramdisk (single channel meory mapped virtual disk)    => rdk_driver
[258]16//
[295]17// It can exist only one block-device type in the architecture, that must be
18// defined by one of the following configuration variables in hard_config.h file:
19// USE_IOC_BDV, USE_IOC_SDC, USE_IOC_HBA, USE_IOC_RDK.
[258]20//
[295]21// Any physical driver xxx must provide the following API:
22// - _xxx_init()
23// - _xxx_read()
24// - _xxx_write()
25// - _xxx_get_status()
26// - _xxx_get_block_size()
27// The "channel" parameter is no transmited to single channel devices.
[258]28//
[295]29// The _ioc_read() and _ioc_write() functions are always blocking for
30// the calling user program.
[258]31//
[295]32// These functions compute the physical address of the memory buffer before
33// calling the proper physical device. They can be called in 3 modes:
[258]34//
[295]35// - In BOOT mode, these functions use the buffer virtual address
36//   as a physical address if the MMU is not activated.
37//   They make a V2P translation if the MMU is activated.
38//   This mode is used to load the map.bin file (before memory activation),
39//   or to load the various .elf files (after MMU activation).
[258]40//
[295]41// - In KERNEL mode, these functions make a V2P translation to
42//   compute the buffer physical address.
43//   There is no checking of user access right to the memory buffer. 
44//   This mode must be used for an "open" system call.
45//
46// - In USER mode, these functions make a V2P translation to
47//   compute the buffer physical address.
48//   The user access right to the memory buffer are checked. 
49//   This mode must be used for a "read" or "write" system call.
50//
[258]51// The IOMMU can be activated or not:
52//
53// 1) When the IOMMU is used, a fixed size 2Mbytes vseg is allocated to
54// the IOC peripheral, in the I/O virtual space, and the user buffer is
55// dynamically remapped in the IOMMU page table. The corresponding entry
56// in the IOMMU PT1 is defined by the kernel _ioc_iommu_ix1 variable.
57// The number of pages to be unmapped is stored in the _ioc_npages variable.
58// The number of PT2 entries is dynamically computed and stored in the
59// kernel _ioc_iommu_npages variable. It cannot be larger than 512.
60// The user buffer is unmapped by the _ioc_completed() function when
61// the transfer is completed.
62//
63// 2/ If the IOMMU is not used, we check that  the user buffer is mapped to a
64// contiguous physical buffer (this is generally true because the user space
65// page tables are statically constructed to use contiguous physical memory).
66//
67// Finally, the memory buffer must fulfill the following conditions:
68// - The buffer must be word aligned,
69// - The buffer must be mapped in user space for an user access,
70// - The buffer must be writable in case of (to_mem) access,
71// - The total number of physical pages occupied by the user buffer cannot
72//   be larger than 512 pages if the IOMMU is activated,
73// - All physical pages occupied by the user buffer must be contiguous
74//   if the IOMMU is not activated.
75// An error code is returned if these conditions are not verified.
[295]76//
77// The "seg_ioc_base" virtual base address of the segment containing the
78// memory-mapped registers of the device must be defined in the giet_vsegs.ld file.
79// If the RAMDISK is used, an extra memory segment with virtual base address
80// "seg_ramdisk_base" must be defined in the giet_vsegs.ld file.
[258]81///////////////////////////////////////////////////////////////////////////////////
[295]82// Implementation note:
83// In order to share the code, the two _ioc_read() and _ioc_write() functions
84// call the same _ioc_access() function.
[258]85///////////////////////////////////////////////////////////////////////////////////
86
87#include <giet_config.h>
88#include <ioc_driver.h>
[295]89#include <bdv_driver.h>
90#include <hba_driver.h>
91#include <sdc_driver.h>
92#include <rdk_driver.h>
[258]93#include <utils.h>
94#include <tty_driver.h>
95#include <iob_driver.h>
96#include <ctx_handler.h>
97#include <mmc_driver.h>
98#include <vmem.h>
99
100#if !defined( USE_IOB )
101# error: You must define USE_IOB in the hard_config.h file
102#endif
103
104#if !defined(GIET_USE_IOMMU)
105# error: You must define GIET_USE_IOMMU in the giet_config.h file
106#endif
107
[295]108#if (USE_IOC_BDV + USE_IOC_SPI + USE_IOC_HBA + USE_IOC_RDK) != 1
109# error: You must use only one IOC controller type (BDV or SPI or HBA or RDK)
[289]110#endif
111
[295]112#if USE_IOC_BDV
[289]113# include <bdv_driver.h>
114#endif
115
[295]116#if USE_IOC_SPI
[289]117# include <sdc_driver.h>
118#endif
119
[295]120#if USE_IOC_HBA
[289]121# include <hba_driver.h>
122#endif
123
[295]124#if USE_IOC_RDK
125# include <rdk_driver.h>
126#endif
[289]127
[295]128///////////////////////////////////////////////////////////////////////////////
129// IOC global variables
130///////////////////////////////////////////////////////////////////////////////
131
[258]132#define in_unckdata __attribute__((section (".unckdata")))
133
134in_unckdata volatile unsigned int _ioc_iommu_ix1 = 0;
135in_unckdata volatile unsigned int _ioc_iommu_npages; 
136
137///////////////////////////////////////////////////////////////////////////////
138// This function transfer data between a memory buffer and the block device.
139// The buffer lentgth is (count*block_size) bytes.
140// Arguments are:
141// - to_mem     : from external storage to memory when non 0.
[295]142// - mode       : BOOT_PA / BOOT_VA / KERNEL / USER
[258]143// - lba        : first block index on the external storage.
144// - buf_vaddr  : virtual base address of the memory buffer.
145// - count      : number of blocks to be transfered.
146// Returns 0 if success, > 0 if error.
147///////////////////////////////////////////////////////////////////////////////
148static unsigned int _ioc_access( unsigned int to_mem,
[295]149                                 unsigned int channel,
[258]150                                 unsigned int mode,
151                                 unsigned int lba,
152                                 unsigned int buf_vaddr,
153                                 unsigned int count) 
154{
155
156#if GIET_DEBUG_IOC_DRIVER
[295]157unsigned int procid  = _get_procid();
158unsigned int cid     = procid / NB_PROCS_MAX;
159unsigned int lpid    = procid % NB_PROCS_MAX;
160unsigned int x       = cid >> Y_WIDTH;
161unsigned int y       = cid & ((1<<Y_WIDTH) - 1);
162
163_printf("\n[IOC DEBUG] Processor[%d,%d,%d] enters _ioc_access() at cycle %d\n"
164        " - channel  = %d\n"
165        " - mode     = %d\n"
[313]166        " - vaddr    = %x\n"
[295]167        " - sectors  = %d\n"
[313]168        " - lba      = %x\n",
[295]169        x, y, lpid, _get_proctime(), channel, mode, buf_vaddr, count, lba );
[258]170#endif
171
172    unsigned int error;            // return value
173    unsigned int pt_vbase;         // page table vbase address
174    unsigned int vpn_min;          // first virtuel page index covering buffer
175    unsigned int vpn_max;          // last virtual page index covering buffer
176    unsigned int vpn;              // current virtual page index
177    unsigned int ppn;              // physical page number
178    unsigned int flags;            // page protection flags
179    unsigned int ix2;              // page index in IOMMU PT1 page table
180    unsigned int ppn_first;        // first physical page number for user buffer
181    unsigned int buf_xaddr = 0;    // user buffer virtual address in IO space (if IOMMU)
182    paddr_t      buf_paddr = 0;    // user buffer physical address (if no IOMMU),
183
184    // check buffer alignment
185    if ((unsigned int) buf_vaddr & 0x3)
186    {
[295]187        _printf("\n[GIET ERROR] in _ioc_access() : buffer not word aligned\n");
188        _exit(); 
[258]189    }
190
[295]191    // check channel
192    if ( (USE_IOC_HBA == 0) && (channel > 0) )
193    {
194        _printf("\n[GIET ERROR] in _ioc_access() : channel must be 0 when HBA not used\n");
195        _exit(); 
196    }
197
[258]198    unsigned int length = count << 9;  // count * 512 bytes
199
[295]200    // computing memory buffer physical address
201    if ( (mode == IOC_BOOT_MODE) && ((_get_mmu_mode() & 0x4) == 0) ) // identity mapping
[258]202    {
203        buf_paddr = (paddr_t)buf_vaddr;
204    }
[295]205    else                                                    // V2P translation required
[258]206    {
207        // get page table virtual address
208        pt_vbase = _get_context_slot(CTX_PTAB_ID);
[295]209        vpn_min  = buf_vaddr >> 12;
210        vpn_max  = (buf_vaddr + length - 1) >> 12;
[258]211
212        // loop on all virtual pages covering the user buffer
[295]213        for (vpn = vpn_min, ix2 = 0 ; vpn <= vpn_max ; vpn++, ix2++ ) 
[258]214        {
215            // get ppn and flags for each vpn
216            unsigned int ko = _v2p_translate( (page_table_t*)pt_vbase,
217                                              vpn,
218                                              &ppn,
219                                              &flags);
220            // check access rights
221            if ( ko )
222            {
[295]223                _printf("\n[GIET ERROR] in _ioc_access() : buffer unmapped\n");
[258]224                return 1; 
225            }
226
227            if ( (mode == IOC_USER_MODE) && ((flags & PTE_U) == 0) )
228            {
[295]229                _printf("\n[GIET ERROR] in _ioc_access() : buffer not user accessible\n");
[258]230                return 1; 
231            }
232
233            if ( ((flags & PTE_W) == 0 ) && to_mem )
234            {
[295]235                _printf("\n[GIET ERROR] in _ioc_access() : buffer not writable\n");
[258]236                return 1; 
237            }
238
239            // save first ppn value
240            if (ix2 == 0) ppn_first = ppn;
241
242#if GIET_USE_IOMMU
243 
244            // check buffer length < 2 Mbytes
245            if (ix2 > 511) // check buffer length < 2 Mbytes
246            {
[295]247                _printf("\n[GIET ERROR] in _ioc_access() : user buffer > 2 Mbytes\n");
[258]248                return 1; 
249            }
250            // map the physical page in IOMMU page table
251            _iommu_add_pte2( _ioc_iommu_ix1,    // PT1 index
252                             ix2,               // PT2 index
253                             ppn,               // Physical page number   
254                             flags );           // Protection flags
255
256            // compute user buffer virtual adress in IO space
257            buf_xaddr = (_ioc_iommu_ix1) << 21 | (buf_vaddr & 0xFFF);
258
259#else
260
261            // check that physical pages are contiguous
262            if ((ppn - ppn_first) != ix2) 
263            {
[295]264                _printf("[GIET ERROR] in _ioc_access() : split physical buffer\n");
[258]265                return 1; 
266            }
267
268            // compute user buffer physical adress
269            buf_paddr = (((paddr_t)ppn_first) << 12) | (buf_vaddr & 0xFFF);
270#endif           
271
272        } // end for vpn
273    }
274
275#if GIET_USE_IOMMU
276
277    // register the number of pages to be unmapped in IOMMU
278    _ioc_iommu_npages = (vpn_max - vpn_min) + 1;
279
280#endif
281
282    if ( to_mem ) // memory write : invalidate data caches
283    {
284        // L1 cache
285        if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate((void *) buf_vaddr, length);
286
287        // L2 cache (only if IOB used)
[297]288        if ( USE_IOB ) _mmc_inval( buf_paddr, length );
[258]289    }
290    else         // memory read : update data caches
291    {
[295]292        // L1 cache : nothing to do for L1 write-through
[258]293
294        // L2 cache (only if IOB used)
[297]295        if ( USE_IOB ) _mmc_sync( buf_paddr, length );
[258]296    }
297
[289]298    if ( GIET_USE_IOMMU ) buf_paddr = (paddr_t) buf_xaddr;
[258]299
[295]300    ///////////////////////////////////////////
301    // select the proper physical device
302    ///////////////////////////////////////////
303
304#if       ( USE_IOC_BDV )
305
306#if GIET_DEBUG_IOC_DRIVER
307_printf("\n[IOC DEBUG] Calling BDV driver\n");
[258]308#endif
[295]309        if (to_mem) error = _bdv_read ( mode, lba, buf_paddr, count);
310        else        error = _bdv_write( mode, lba, buf_paddr, count);
[258]311
[295]312#elif ( USE_IOC_SPI )
313
314#if GIET_DEBUG_IOC_DRIVER
315_printf("\n[IOC DEBUG] Calling SPI driver\n");
316#endif
317        if (to_mem) error = _sdc_read (mode, lba, buf_paddr, count);
318        else        error = _sdc_write(mode, lba, buf_paddr, count);
319
320#elif ( USE_IOC_HBA )
321
322#if GIET_DEBUG_IOC_DRIVER
323_printf("\n[IOC DEBUG] Calling HBA driver\n");
324#endif
325        if (to_mem) error = _hba_read (channel, mode, lba, buf_paddr, count);
326        else        error = _hba_write(channel, mode, lba, buf_paddr, count);
327
328#elif ( USE_IOC_RDK )
329
330#if GIET_DEBUG_IOC_DRIVER
331_printf("\n[IOC DEBUG] Calling RDK driver\n");
332#endif
333        if (to_mem) error = _rdk_read (lba, buf_vaddr, count);
334        else        error = _rdk_write(lba, buf_vaddr, count);
335
336#endif
337
[258]338    return error;
339} // end _ioc_access()
340
341///////////////////////////////////////////////////////////////////////////////
342// This function cheks block size, and activates the IOC interrupts.
343// Return 0 for success.
344///////////////////////////////////////////////////////////////////////////////
[289]345unsigned int _ioc_init( unsigned int channel )
[258]346{
[295]347
348#if   ( USE_IOC_BDV )
349
350    return _bdv_init();
351
352#elif ( USE_IOC_SPI )
353
354    return _sdc_init();
355   
356#elif ( USE_IOC_HBA )
357
[289]358    return _hba_init( channel );
[295]359   
360#elif ( USE_IOC_RDK )
361
362    return _rdk_init();
363   
[289]364#endif
[295]365   
[258]366}
367
368///////////////////////////////////////////////////////////////////////////////
369// Transfer data from the block device to a memory buffer.
[295]370// - mode     : BOOT_PA / BOOT_VA / KERNEL / USER
[258]371// - lba      : first block index on the block device
372// - buffer   : base address of the memory buffer (must be word aligned)
373// - count    : number of blocks to be transfered.
374// Returns 0 if success, > 0 if error.
375///////////////////////////////////////////////////////////////////////////////
[295]376unsigned int _ioc_read( unsigned int channel,
377                        unsigned int mode, 
[258]378                        unsigned int lba, 
379                        void*        buffer, 
380                        unsigned int count) 
381{
382    return _ioc_access( 1,        // read access
[295]383                        channel,
[258]384                        mode, 
385                        lba,
386                        (unsigned int) buffer,
387                        count );
388}
389
390///////////////////////////////////////////////////////////////////////////////
391// Transfer data from a memory buffer to the block device.
[295]392// - mode     : BOOT_PA / BOOT_VA / KERNEL / USER
[258]393// - lba      : first block index on the block device
394// - buffer   : base address of the memory buffer (must be word aligned)
395// - count    : number of blocks to be transfered.
396// Returns 0 if success, > 0 if error.
397///////////////////////////////////////////////////////////////////////////////
[295]398unsigned int _ioc_write( unsigned int channel,
399                         unsigned int mode, 
[258]400                         unsigned int lba, 
401                         const void*  buffer, 
402                         unsigned int count ) 
403{
404    return _ioc_access( 0,        // write access
[295]405                        channel,
[258]406                        mode, 
407                        lba,
408                        (unsigned int) buffer,
409                        count );
410}
411
412///////////////////////////////////////////////////////////////////////////////
[279]413// This function returns in the status variable, the transfert status, and
414// acknowledge the IRQ if the IOC controler is not busy.
415// Returns 0 if success, > 0 if error
[258]416///////////////////////////////////////////////////////////////////////////////
[295]417unsigned int _ioc_get_status( unsigned int  channel )
[258]418{
[295]419
420#if   ( USE_IOC_BDV )
421
422    return _bdv_get_status( );
423
424#elif ( USE_IOC_SPI )
425
426    return _sdc_get_status( );
427
428#elif ( USE_IOC_HBA )
429
430    return _hba_get_status( channel );
431
432#elif ( USE_IOC_RDK )
433
434    _printf("[GIET ERROR] _ioc_get_status() should not be called");
435    _printf(" when RAMDISK  is used...\n");
436    _exit();
437
438    return 0;
439
[289]440#endif
[295]441
[258]442}
443
444///////////////////////////////////////////////////////////////////////////////
445// This function returns the block_size with which the IOC has been configured.
446///////////////////////////////////////////////////////////////////////////////
447unsigned int _ioc_get_block_size() 
448{
[295]449
450#if   ( USE_IOC_BDV )
451
[289]452    return _bdv_get_block_size();
[295]453   
454#elif ( USE_IOC_SPI )
455
[289]456    return _sdc_get_block_size();
[295]457   
458#elif ( USE_IOC_HBA )
459
[289]460    return _hba_get_block_size();
[295]461   
462#elif ( USE_IOC_RDK )
463
464    return 512;
465
[289]466#endif
[295]467
[258]468}
469
470
471// Local Variables:
472// tab-width: 4
473// c-basic-offset: 4
474// c-file-offsets:((innamespace . 0)(inline-open . 0))
475// indent-tabs-mode: nil
476// End:
477// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
478
Note: See TracBrowser for help on using the repository browser.