summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2012-12-22 11:49:20 +0100
committerRichard Braun <rbraun@sceen.net>2012-12-22 11:49:20 +0100
commit055142133fd561a27f9b9765090fc6c1aac0b3dd (patch)
treee4ba89a392210e6184717e1b2eccabe212b380a2
parent5489c1eb6e2a863d7450bb0ce3f9041000d41822 (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.c10
-rw-r--r--arch/x86/machine/param.h23
-rw-r--r--vm/vm_phys.c21
-rw-r--r--vm/vm_phys.h9
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);