diff options
Diffstat (limited to 'arch/s390/kernel/mem_detect.c')
-rw-r--r-- | arch/s390/kernel/mem_detect.c | 69 |
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 | } |
64 | EXPORT_SYMBOL(detect_memory_layout); | 64 | EXPORT_SYMBOL(detect_memory_layout); |
65 | |||
66 | /* | ||
67 | * Create memory hole with given address, size, and type | ||
68 | */ | ||
69 | void 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 | } | ||