203 lines
6.6 KiB
C
203 lines
6.6 KiB
C
|
/* Copyright (C) 2004 David Decotigny
|
||
|
Copyright (C) 2000 The KOS Team
|
||
|
|
||
|
This program 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; either version 2
|
||
|
of the License, or (at your option) any later version.
|
||
|
|
||
|
This program 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 this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||
|
USA.
|
||
|
*/
|
||
|
#ifndef _SOS_PHYSMEM_H_
|
||
|
#define _SOS_PHYSMEM_H_
|
||
|
|
||
|
/**
|
||
|
* @file physmem.h
|
||
|
*
|
||
|
* Physical pages of memory
|
||
|
*/
|
||
|
|
||
|
#include <sos/errno.h>
|
||
|
#include <sos/types.h>
|
||
|
#include <sos/macros.h>
|
||
|
|
||
|
/** The size of a physical page (arch-dependent) */
|
||
|
#define SOS_PAGE_SIZE (4*1024)
|
||
|
|
||
|
/** The corresponding shift */
|
||
|
#define SOS_PAGE_SHIFT 12 /* 4 kB = 2^12 B */
|
||
|
|
||
|
/** The corresponding mask */
|
||
|
#define SOS_PAGE_MASK ((1<<12) - 1)
|
||
|
|
||
|
#define SOS_PAGE_ALIGN_INF(val) \
|
||
|
SOS_ALIGN_INF((val), SOS_PAGE_SIZE)
|
||
|
#define SOS_PAGE_ALIGN_SUP(val) \
|
||
|
SOS_ALIGN_SUP((val), SOS_PAGE_SIZE)
|
||
|
#define SOS_IS_PAGE_ALIGNED(val) \
|
||
|
SOS_IS_ALIGNED((val), SOS_PAGE_SIZE)
|
||
|
|
||
|
/**
|
||
|
* This is the reserved physical interval for the x86 video memory and
|
||
|
* BIOS area. In physmem.c, we have to mark this area as "nonfree" in
|
||
|
* order to prevent from allocating it. And in paging.c, we'd better
|
||
|
* map it in virtual space if we really want to be able to print to
|
||
|
* the screen (for debugging purpose, at least): for this, the
|
||
|
* simplest is to identity-map this area in virtual space (note
|
||
|
* however that this mapping could also be non-identical).
|
||
|
*/
|
||
|
#define BIOS_N_VIDEO_START 0xa0000
|
||
|
#define BIOS_N_VIDEO_END 0x100000
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Initialize the physical memory subsystem, for the physical area [0,
|
||
|
* ram_size). This routine takes into account the BIOS and video
|
||
|
* areas, to prevent them from future allocations.
|
||
|
*
|
||
|
* @param ram_size The size of the RAM that will be managed by this subsystem
|
||
|
*
|
||
|
* @param kernel_core_base The lowest address for which the kernel
|
||
|
* assumes identity mapping (ie virtual address == physical address)
|
||
|
* will be stored here
|
||
|
*
|
||
|
* @param kernel_core_top The top address for which the kernel
|
||
|
* assumes identity mapping (ie virtual address == physical address)
|
||
|
* will be stored here
|
||
|
*/
|
||
|
sos_ret_t sos_physmem_subsystem_setup(sos_size_t ram_size,
|
||
|
/* out */sos_paddr_t *kernel_core_base,
|
||
|
/* out */sos_paddr_t *kernel_core_top);
|
||
|
|
||
|
/**
|
||
|
* Retrieve the total number of pages, and the number of free pages
|
||
|
*/
|
||
|
sos_ret_t sos_physmem_get_state(/* out */sos_count_t *total_ppages,
|
||
|
/* out */sos_count_t *nonfree_ppages);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Get a free page.
|
||
|
*
|
||
|
* @return The (physical) address of the (physical) page allocated, or
|
||
|
* NULL when none currently available.
|
||
|
*
|
||
|
* @param can_block TRUE if the function is allowed to block
|
||
|
* @note The page returned has a reference count equal to 1.
|
||
|
*/
|
||
|
sos_paddr_t sos_physmem_ref_physpage_new(sos_bool_t can_block);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Increment the reference count of a given physical page. Useful for
|
||
|
* VM code which tries to map a precise physical address.
|
||
|
*
|
||
|
* @param ppage_paddr Physical address of the page (MUST be page-aligned)
|
||
|
*
|
||
|
* @return TRUE when the page was previously referenced, FALSE when
|
||
|
* the page was previously unreferenced, <0 when the page address is
|
||
|
* invalid.
|
||
|
*/
|
||
|
sos_ret_t sos_physmem_ref_physpage_at(sos_paddr_t ppage_paddr);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Decrement the reference count of the given physical page. When the
|
||
|
* reference count of the page reaches 0, the page is marked free, ie
|
||
|
* is available for future sos_physmem_ref_physpage_new()
|
||
|
*
|
||
|
* @param ppage_paddr Physical address of the page (MUST be page-aligned)
|
||
|
*
|
||
|
* @return FALSE when the page is still referenced, TRUE when the page
|
||
|
* is now unreferenced, <0 when the page address is invalid
|
||
|
*/
|
||
|
sos_ret_t sos_physmem_unref_physpage(sos_paddr_t ppage_paddr);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Return the reference count of the given page
|
||
|
*
|
||
|
* @return >= 0 (the referebce count of the page) if the physical
|
||
|
* address is valid, or an error status
|
||
|
*/
|
||
|
sos_ret_t sos_physmem_get_physpage_refcount(sos_paddr_t ppage_paddr);
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* In some cases (Page Tables on x86 for example), the physical pages
|
||
|
* might contain a set of slots available for "allocation" (x86
|
||
|
* example: a PT contains a set of PTE). We provide here a set of
|
||
|
* functions to manage a per-page additional counter that holds this
|
||
|
* number of slots currently in use in the page.
|
||
|
*
|
||
|
* A newly allocated physical page has a occupation count of 0.
|
||
|
*
|
||
|
* The management of this counter is up to the subsystem that manages
|
||
|
* the page (mainly: paging), however a simple set of rules applies:
|
||
|
* - it can only be incremented/decremented if the page is referenced
|
||
|
* - when it reaches 0, no automatic action is undertaken
|
||
|
* The first rule means in particular that a page whose reference
|
||
|
* count reaches 0 (=> being freed) cannot have a occupation_cnt
|
||
|
* value > 0 ! The system will be HALTED if this ever happens
|
||
|
*/
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Increment the occupation count of the given physical page.
|
||
|
*
|
||
|
* @param ppage_paddr Physical address of the page (MUST be page-aligned)
|
||
|
*
|
||
|
* @return TRUE when the occupation count was previously NON-ZERO, FALSE
|
||
|
* when this occupation count was 0, <0 when the page address is invalid.
|
||
|
*
|
||
|
* @note the page MUST be marked as REFERENCED by somebody !
|
||
|
*/
|
||
|
sos_ret_t sos_physmem_inc_physpage_occupation(sos_paddr_t ppage_paddr);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Decrement the occupation count of the given physical page.
|
||
|
*
|
||
|
* @param ppage_paddr Physical address of the page (MUST be page-aligned)
|
||
|
*
|
||
|
* @return FALSE when the occupation count is still NON-ZERO, TRUE when the
|
||
|
* page now is ZERO, <0 when the page address is invalid
|
||
|
*
|
||
|
* @note the page MUST be marked as REFERENCED by somebody !
|
||
|
*/
|
||
|
sos_ret_t sos_physmem_dec_physpage_occupation(sos_paddr_t ppage_paddr);
|
||
|
|
||
|
|
||
|
#include <sos/kmem_vmm.h>
|
||
|
|
||
|
/**
|
||
|
* Return the kernel memory allocation range associated with the given
|
||
|
* physical page, or NULL when page has no associated range
|
||
|
*
|
||
|
* @param ppage_paddr Physical address of the page (MUST be page-aligned)
|
||
|
*/
|
||
|
struct sos_kmem_range* sos_physmem_get_kmem_range(sos_paddr_t ppage_paddr);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Set the kernel memory allocation range associated to the given
|
||
|
* physical page.
|
||
|
*
|
||
|
* @param ppage_paddr Physical address of the page (MUST be page-aligned)
|
||
|
*
|
||
|
* @return error if page is invalid
|
||
|
*/
|
||
|
sos_ret_t sos_physmem_set_kmem_range(sos_paddr_t ppage_paddr,
|
||
|
struct sos_kmem_range *range);
|
||
|
|
||
|
#endif /* _SOS_PHYSMEM_H_ */
|