/*
 * hal_gpt.h - Generic Page Table API definition.
 *
 * Authors  Alain Greiner (2016)
 *
 * 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-MKH; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#ifndef _GPT_H_
#define _GPT_H_

#include <hal_types.h>

/////////////////////////////////////////////////////////////////////////////////////////
//           Generic Page Table Definition (implementation in hal_gpt.c)
//
// It is specified as a simple (one dimensionnal) array indexed by the VPN (vpn_t type),
// even if implementations can use a more sophisticated organistion (two-levels or more).
// - The number of entries (number of pages in a virtual space) is architecture 
//   dependant, and is defined as (CONFIG_USER_SPACE_SIZE / CONFIG_PPM_PAGE_SIZE).
// - Each entry contains a Physical Page Number (ppn_t type),  and a set of attributes,
//   defined as masks on a 32 bits-vector.
//
// Any arch-specific implementation must implement this API. 
/////////////////////////////////////////////////////////////////////////////////////////

/****  Forward declarations  ****/

struct page_s;

/****************************************************************************************
 * These global variables defines the masks for the Generic Page Table Entry attributes.
 * The actual values must be defined in the implementation (hal_gpt.c file).
 ***************************************************************************************/

extern uint32_t  GPT_MAPPED;         /*! PTE is mapepd                                 */
extern uint32_t  GPT_SMALL;          /*! PTE is a small page                           */
extern uint32_t  GPT_READABLE;       /*! PTE is readable                               */
extern uint32_t  GPT_WRITABLE;       /*! PTE is writable                               */
extern uint32_t  GPT_EXECUTABLE;     /*! PTE is executable                             */
extern uint32_t  GPT_CACHABLE;       /*! PTE can be cached                             */
extern uint32_t  GPT_USER;           /*! PTE is user accessible                        */
extern uint32_t  GPT_DIRTY;          /*! PTE has been "recently" written               */
extern uint32_t  GPT_ACCESSED;       /*! PTE has been "recently" accessed              */
extern uint32_t  GPT_GLOBAL;         /*! PTE is kept in TLB at context swtch           */
extern uint32_t  GPT_COW;            /*! PTE must be copied on write                   */
extern uint32_t  GPT_SWAP;           /*! PTE swaped on disk (non implemented yet)      */
extern uint32_t  GPT_LOCKED;         /*! PTE is protected against concurrent access    */

/****************************************************************************************
 * This structure define the Generic Page Table descriptor.
 ***************************************************************************************/

typedef struct gpt_s
{
	void           * ptr;    /*! pointer on GPT root (must be page aligned)            */
	ppn_t            ppn;    /*! PPN of GPT root                                       */
    struct page_s  * page;   /*! pointer on page descriptor for GPT root               */
}
gpt_t;


/****************************************************************************************
 * This function allocates physical memory for PT1 and initialize page table descriptor.
 ****************************************************************************************
 * @ gpt     : pointer on generic page table descriptor.
 * @ returns 0 if success / returns ENOMEM if error.
 ***************************************************************************************/
error_t hal_gpt_create( gpt_t * gpt );

/****************************************************************************************
 * This function releases all memory dynamically allocated for a generic page table.
 * For a multi-levels radix tree implementation, it includes all nodes in the tree.
 * If the calling thread is running in the reference cluster, it checks that user PTE 
 * entries are unmapped, and release the mapped physical pages.
 * The kernel pages are not released.
 ****************************************************************************************
 * @ gpt     : pointer on generic page table descriptor.
 ***************************************************************************************/
void hal_gpt_destroy( gpt_t * gpt);

/****************************************************************************************
 * This function print on the kernel terminal the content of a generic page table.
 ****************************************************************************************
 * @ gpt     : pointer on generic page table descriptor.
 ***************************************************************************************/
void hal_gpt_print( gpt_t * gpt);

/****************************************************************************************
 * This blocking fonction get a lock on a PTE (page Table Entry) identified
 * by its VPN, and returns only when the PTE has been successfully locked.
 * If the target PTE is not present, it allocates and map a physical page.
 * A big page cannot be locked.
 ****************************************************************************************
 * @ gpt     : pointer on the generic page table 
 * @ vpn     : virtual page number of the target PTE.
 * @ returns 0 if success / return ENOMEM or EINVAL if error.  
 ***************************************************************************************/
error_t hal_gpt_lock_pte( gpt_t * gpt,
                          vpn_t   vpn );

/****************************************************************************************
 * This function releases the lock on a PTE identified by its VPN.
 ****************************************************************************************
 * @ gpt     : pointer on the generic page table 
 * @ vpn     : virtual page number of the target PTE.
 * @ returns 0 if success / returns EINVAL if error.  
 ***************************************************************************************/
error_t hal_gpt_unlock_pte( gpt_t * gpt, 
                            vpn_t   vpn ); 

/****************************************************************************************
 * This function map a page table entry identified by its VPN, from values defined
 * by the ppn and attr arguments. It allocates physical memory for the local generic
 * page table itself if required.
 ****************************************************************************************
 * @ gpt       : [in] pointer on the page table
 * @ vpn       : [in] virtual page number
 * @ ppn       : [in] physical page number 
 * @ attr      : [in] generic attributes
 * @ returns 0 if success / returns ENOMEM if error
 ***************************************************************************************/
error_t hal_gpt_set_pte( gpt_t    * gpt,
                         vpn_t      vpn,
                         ppn_t      ppn,
                         uint32_t   attr );

/****************************************************************************************
 * This function unmap a page table entry identified by its VPN.
 * If the calling thread is running in the reference cluster, it send a broadcast RPC
 * to update all others page table copies.
 ****************************************************************************************
 * @ gpt       : [in] pointer on the page table
 * @ vpn       : [in] virtual page number
 ***************************************************************************************/
void hal_gpt_reset_pte( gpt_t * gpt,
                        vpn_t   vpn );

/****************************************************************************************
 * This function returns in the ppn and attr arguments the value of a page table
 * entry identified by its VPN.  It returns attr == 0 if the page is not mapped.
 ****************************************************************************************
 * @ gpt       : [in]  pointer on the page table
 * @ vpn       : [in]  virtual page number
 * @ attr      : [out] generic attributes
 * @ ppn       : [out] physical page number 
 ***************************************************************************************/
void hal_gpt_get_pte( gpt_t    * gpt,
                      vpn_t      vpn,
                      uint32_t * attr,
                      ppn_t    * ppn );
 

#endif	/* _GPT_H_ */
