/*
 * kmem.h - kernel unified memory allocator interface
 *
 * Authors  Alain Greiner (2016,2017,2018,2019)
 *
 * Copyright (c) UPMC Sorbonne Universites
 *
 * This file is part of ALMOS-MKH.
 *
 * ALMOS-MKH is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2.0 of the License.
 *
 * ALMOS-MKH 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 ALMOS; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef _KMEM_H_
#define _KMEM_H_

#include <hal_kernel_types.h>
#include <kcm.h>

/*************************************************************************************
 * This enum defines the three Kernel Memory Allocaror types 
 ************************************************************************************/

enum
{
    KMEM_PPM              = 0,   /*! PPM allocator                                  */
    KMEM_KCM              = 1,   /*! KCM allocator                                  */
    KMEM_KHM              = 2,   /*! KHM allocator                                  */
};

/*************************************************************************************
 * This defines the generic Allocation Flags that can be associated to
 * a Kernel Memory Request.
 ************************************************************************************/

#define AF_NONE       0x0000   // no attributes
#define AF_KERNEL     0x0001   // for kernel use
#define AF_ZERO       0x0002   // must be reset to 0

/*************************************************************************************
 * This structure defines a Kernel Memory Request.
 ************************************************************************************/

typedef struct kmem_req_s
{
    uint32_t      type;   /*! KMEM_PPM / KMEM_KCM / KMEM_KHM                        */
    uint32_t      order;  /*! PPM: ln2(pages) / KCM: ln2(bytes) / KHM: bytes        */
    uint32_t      flags;  /*! request attributes                                    */
    void        * ptr;    /*! local pointer on allocated buffer (only used by free) */
}
kmem_req_t;

/*************************************************************************************
 * These two functions allocate physical memory in a local or remote cluster
 * as specified by the kmem_req_t request descriptor, and return a local pointer
 * on the allocated buffer. It uses three specialised physical memory allocators:
 * - PPM (Physical Pages Manager) allocates N contiguous small physical pages.
 *       N is a power of 2, and req.order = ln(N). Implement the buddy algorithm.
 * - KCM (Kernel Cache Manager) allocates aligned blocks of M bytes from a cache.
 *       M is a power of 2, and req.order = ln( M ). One cache per block size.
 * - KHM (Kernel Heap Manager) allocates physical memory buffers of M bytes,
 *       M can have any value, and req.order = M.
 *
 * WARNING: the physical memory allocated with a given allocator type must be
 *          released using the same allocator type.
 *************************************************************************************
 * @ cxy   : target cluster identifier for a remote access.
 * @ req   : local pointer on allocation request.
 * @ return local pointer on allocated buffer if success / return NULL if no memory.
 ************************************************************************************/
void * kmem_alloc( kmem_req_t * req );

void * kmem_remote_alloc( cxy_t        cxy,
                          kmem_req_t * req );

/*************************************************************************************
 * These two functions release previously allocated physical memory, as specified
 * by the <type> and <ptr> fields of the kmem_req_t request descriptor.
 *************************************************************************************
 * @ cxy   : target cluster identifier for a remote access.
 * @ req : local pointer to request descriptor.
 ************************************************************************************/
void  kmem_free ( kmem_req_t * req );

void  kmem_remote_free( cxy_t        cxy,
                        kmem_req_t * req );


#endif	/* _KMEM_H_ */
