diff options
author | Richard Braun <rbraun@sceen.net> | 2012-12-22 11:49:20 +0100 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2012-12-22 11:49:20 +0100 |
commit | 055142133fd561a27f9b9765090fc6c1aac0b3dd (patch) | |
tree | e4ba89a392210e6184717e1b2eccabe212b380a2 | |
parent | 5489c1eb6e2a863d7450bb0ce3f9041000d41822 (diff) |
vm/vm_phys: add segment allocation function
Architecture specific code sometimes has constraints on the location of some
data structures in physical memory. This interface provides a simple way to
allocate physical memory from segments that fulfill these constraints. If
they are stronger, or needed by machine independent code, another (more
complicated) interface will be needed.
-rw-r--r-- | arch/x86/machine/biosmem.c | 10 | ||||
-rw-r--r-- | arch/x86/machine/param.h | 23 | ||||
-rw-r--r-- | vm/vm_phys.c | 21 | ||||
-rw-r--r-- | vm/vm_phys.h | 9 |
4 files changed, 45 insertions, 18 deletions
diff --git a/arch/x86/machine/biosmem.c b/arch/x86/machine/biosmem.c index 3309722e..03afddd6 100644 --- a/arch/x86/machine/biosmem.c +++ b/arch/x86/machine/biosmem.c @@ -547,7 +547,8 @@ biosmem_map_find_avail(phys_addr_t *phys_start, phys_addr_t *phys_end) static void __init biosmem_load_segment(const char *name, phys_addr_t phys_start, phys_addr_t phys_end, phys_addr_t avail_start, - phys_addr_t avail_end, unsigned int seglist_prio) + phys_addr_t avail_end, unsigned int seg_index, + unsigned int seglist_prio) { if ((avail_start < phys_start) || (avail_start > phys_end)) avail_start = phys_start; @@ -556,7 +557,7 @@ biosmem_load_segment(const char *name, phys_addr_t phys_start, avail_end = phys_end; vm_phys_load(name, phys_start, phys_end, avail_start, avail_end, - seglist_prio); + seg_index, seglist_prio); } void __init @@ -575,7 +576,7 @@ biosmem_setup(void) if (!error) biosmem_load_segment("normal", phys_start, phys_end, biosmem_heap_free, biosmem_heap_end, - VM_PHYS_SEGLIST_NORMAL); + VM_PHYS_SEG_NORMAL, VM_PHYS_SEGLIST_NORMAL); #ifdef VM_PHYS_HIGHMEM_LIMIT phys_start = VM_PHYS_NORMAL_LIMIT; @@ -584,7 +585,8 @@ biosmem_setup(void) if (!error) biosmem_load_segment("highmem", phys_start, phys_end, - phys_start, phys_end, VM_PHYS_SEGLIST_HIGHMEM); + phys_start, phys_end, + VM_PHYS_SEG_HIGHMEM, VM_PHYS_SEGLIST_HIGHMEM); #endif /* VM_PHYS_HIGHMEM_LIMIT */ } diff --git a/arch/x86/machine/param.h b/arch/x86/machine/param.h index 964b289e..d9fd2241 100644 --- a/arch/x86/machine/param.h +++ b/arch/x86/machine/param.h @@ -62,6 +62,10 @@ #define STACK_SIZE PAGE_SIZE /* + * Virtual memory properties. + */ + +/* * User space boundaries. */ #define VM_MIN_ADDRESS DECL_CONST(0, UL) @@ -110,8 +114,14 @@ #endif /* __LP64__ */ /* + * Virtual space reserved for kernel map entries. + */ +#define VM_MAP_KENTRY_SIZE DECL_CONST(0x800000, UL) + +/* * Physical memory properties. */ + #ifdef __LP64__ #define VM_MAX_PHYS_SEG 2 #define VM_PHYS_NORMAL_LIMIT DECL_CONST(0x100000000, UL) @@ -128,6 +138,12 @@ #endif /* __LP64__ */ /* + * Physical segment indexes. + */ +#define VM_PHYS_SEG_NORMAL 0 +#define VM_PHYS_SEG_HIGHMEM 1 + +/* * Number of physical segment lists. */ #define VM_NR_PHYS_SEGLIST VM_MAX_PHYS_SEG @@ -135,12 +151,7 @@ /* * Segment list priorities. */ -#define VM_PHYS_SEGLIST_HIGHMEM 1 #define VM_PHYS_SEGLIST_NORMAL 0 - -/* - * Virtual space reserved for kernel map entries. - */ -#define VM_MAP_KENTRY_SIZE DECL_CONST(0x800000, UL) +#define VM_PHYS_SEGLIST_HIGHMEM 1 #endif /* _X86_PARAM_H */ diff --git a/vm/vm_phys.c b/vm/vm_phys.c index 7d8e6810..80b9c7b1 100644 --- a/vm/vm_phys.c +++ b/vm/vm_phys.c @@ -127,8 +127,7 @@ struct vm_phys_boot_seg { int vm_phys_ready; /* - * Segment lists, ordered by priority (higher priority lists have lower - * numerical priorities). + * Segment lists, ordered by priority. */ static struct list vm_phys_seg_lists[VM_NR_PHYS_SEGLIST]; @@ -451,7 +450,7 @@ vm_phys_seg_free(struct vm_phys_seg *seg, struct vm_page *page, void __init vm_phys_load(const char *name, phys_addr_t start, phys_addr_t end, phys_addr_t avail_start, phys_addr_t avail_end, - unsigned int seglist_prio) + unsigned int seg_index, unsigned int seglist_prio) { struct vm_phys_boot_seg *boot_seg; struct vm_phys_seg *seg; @@ -460,6 +459,7 @@ vm_phys_load(const char *name, phys_addr_t start, phys_addr_t end, assert(name != NULL); assert(start < end); + assert(seg_index < ARRAY_SIZE(vm_phys_segs)); assert(seglist_prio < ARRAY_SIZE(vm_phys_seg_lists)); if (!vm_phys_load_initialized) { @@ -470,12 +470,11 @@ vm_phys_load(const char *name, phys_addr_t start, phys_addr_t end, vm_phys_load_initialized = 1; } - if (vm_phys_segs_size >= ARRAY_SIZE(vm_phys_segs)) - panic("vm_phys: too many physical segments"); + assert(vm_phys_segs_size < ARRAY_SIZE(vm_phys_segs)); + boot_seg = &vm_phys_boot_segs[seg_index]; + seg = &vm_phys_segs[seg_index]; seg_list = &vm_phys_seg_lists[seglist_prio]; - seg = &vm_phys_segs[vm_phys_segs_size]; - boot_seg = &vm_phys_boot_segs[vm_phys_segs_size]; list_insert_tail(seg_list, &seg->node); seg->start = start; @@ -602,6 +601,14 @@ vm_phys_alloc(unsigned int order) return NULL; } +struct vm_page * +vm_phys_alloc_seg(unsigned int order, unsigned int seg_index) +{ + assert(seg_index < vm_phys_segs_size); + + return vm_phys_seg_alloc(&vm_phys_segs[seg_index], order); +} + void vm_phys_free(struct vm_page *page, unsigned int order) { diff --git a/vm/vm_phys.h b/vm/vm_phys.h index aff124a0..8b02c4b9 100644 --- a/vm/vm_phys.h +++ b/vm/vm_phys.h @@ -38,7 +38,7 @@ extern int vm_phys_ready; */ void vm_phys_load(const char *name, phys_addr_t start, phys_addr_t end, phys_addr_t avail_start, phys_addr_t avail_end, - unsigned int seglist_prio); + unsigned int seg_index, unsigned int seglist_prio); /* * Allocate one physical page. @@ -75,6 +75,13 @@ struct vm_page * vm_phys_lookup_page(phys_addr_t pa); struct vm_page * vm_phys_alloc(unsigned int order); /* + * Allocate physical pages from a specific segment. + * + * This function shouldn't only be called by architecture specific functions. + */ +struct vm_page * vm_phys_alloc_seg(unsigned int order, unsigned int seg_index); + +/* * Release a block of 2^order physical pages. */ void vm_phys_free(struct vm_page *page, unsigned int order); |