/* 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 #include #include /** 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 /** * 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_ */