aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/mem_detect.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/mem_detect.c')
-rw-r--r--arch/s390/kernel/mem_detect.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/arch/s390/kernel/mem_detect.c b/arch/s390/kernel/mem_detect.c
index 0fbe4e32f7ba..19b4568f4cee 100644
--- a/arch/s390/kernel/mem_detect.c
+++ b/arch/s390/kernel/mem_detect.c
@@ -62,3 +62,72 @@ void detect_memory_layout(struct mem_chunk chunk[])
62 arch_local_irq_restore(flags); 62 arch_local_irq_restore(flags);
63} 63}
64EXPORT_SYMBOL(detect_memory_layout); 64EXPORT_SYMBOL(detect_memory_layout);
65
66/*
67 * Create memory hole with given address, size, and type
68 */
69void create_mem_hole(struct mem_chunk chunks[], unsigned long addr,
70 unsigned long size, int type)
71{
72 unsigned long start, end, new_size;
73 int i;
74
75 for (i = 0; i < MEMORY_CHUNKS; i++) {
76 if (chunks[i].size == 0)
77 continue;
78 if (addr + size < chunks[i].addr)
79 continue;
80 if (addr >= chunks[i].addr + chunks[i].size)
81 continue;
82 start = max(addr, chunks[i].addr);
83 end = min(addr + size, chunks[i].addr + chunks[i].size);
84 new_size = end - start;
85 if (new_size == 0)
86 continue;
87 if (start == chunks[i].addr &&
88 end == chunks[i].addr + chunks[i].size) {
89 /* Remove chunk */
90 chunks[i].type = type;
91 } else if (start == chunks[i].addr) {
92 /* Make chunk smaller at start */
93 if (i >= MEMORY_CHUNKS - 1)
94 panic("Unable to create memory hole");
95 memmove(&chunks[i + 1], &chunks[i],
96 sizeof(struct mem_chunk) *
97 (MEMORY_CHUNKS - (i + 1)));
98 chunks[i + 1].addr = chunks[i].addr + new_size;
99 chunks[i + 1].size = chunks[i].size - new_size;
100 chunks[i].size = new_size;
101 chunks[i].type = type;
102 i += 1;
103 } else if (end == chunks[i].addr + chunks[i].size) {
104 /* Make chunk smaller at end */
105 if (i >= MEMORY_CHUNKS - 1)
106 panic("Unable to create memory hole");
107 memmove(&chunks[i + 1], &chunks[i],
108 sizeof(struct mem_chunk) *
109 (MEMORY_CHUNKS - (i + 1)));
110 chunks[i + 1].addr = start;
111 chunks[i + 1].size = new_size;
112 chunks[i + 1].type = type;
113 chunks[i].size -= new_size;
114 i += 1;
115 } else {
116 /* Create memory hole */
117 if (i >= MEMORY_CHUNKS - 2)
118 panic("Unable to create memory hole");
119 memmove(&chunks[i + 2], &chunks[i],
120 sizeof(struct mem_chunk) *
121 (MEMORY_CHUNKS - (i + 2)));
122 chunks[i + 1].addr = addr;
123 chunks[i + 1].size = size;
124 chunks[i + 1].type = type;
125 chunks[i + 2].addr = addr + size;
126 chunks[i + 2].size =
127 chunks[i].addr + chunks[i].size - (addr + size);
128 chunks[i + 2].type = chunks[i].type;
129 chunks[i].size = addr - chunks[i].addr;
130 i += 2;
131 }
132 }
133}