-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incorrect passing of e820 memory map to Linux kexec guests #72
Comments
I've run Fiwix and Linux on QEMU with the following same configuration:
Here are the results: As you can see there is no difference in the memory output. What was your QEMU configuration? |
The problem is only seen if you first boot Fiwix, and then kexec from Fiwix to Linux. Kexec'd Linux will then see an incorrect memory map. The issue was seen on both QEMU 6.2, and on bare metal. |
Can you, please, paste in here the Linux kernel binary you are using? |
This contains the Fiwix and Linux kernels, as well as the kexec loaders for them, as compiled in live-bootstrap. These were captured from one of my bare metal test machines. |
I don't have enough console back history to read the e820 lines as they are on top of the output of the Linux kernel. |
They are, but the syntax is slightly different in Linux than in Fiwix: |
I'm completely unable to redirect the output to the serial line. I've used |
Easiest way to reproduce is probably using live-bootstrap. Apply this patch to rootfs.py to get a serial log:
then use "telnet localhost 45454" or equivalent to start receiving the log on screen (it won't start building until it sees a connection - unfortunately I haven't found a way to keep the normal stdio chardev, and still log to a file). |
I'm sorry, it doesn't work at all. I only see the messages generated by kernel/kexec.c during the transition from Fiwix to Linux. Here is the cmdline I use in Fiwix:
I don't know why the Linux boot messages aren't redirected to the serial line. |
As commented on #bootstrapable IRC channel, I've finally built a simple enough Linux kernel that shows very few boot messages. This made me able to scroll back up to the top of the console history and see the memory map when the Linux kernel is kexec'ed from Fiwix. This is the screen shot of such memory map:
Yes, the problem with all these addresses ending with diff --git a/mm/bios_map.c b/mm/bios_map.c
index b1829bd..4d71295 100644
--- a/mm/bios_map.c
+++ b/mm/bios_map.c
@@ -100,7 +100,7 @@ void bios_map_init(struct multiboot_mmap_entry *bmmap_addr, unsigned int bmmap_l
{
struct multiboot_mmap_entry *bmmap;
unsigned int from_high, from_low, to_high, to_low;
- unsigned long long to;
+ unsigned long long to, to_orig;
int n, type;
bmmap = bmmap_addr;
@@ -112,6 +112,7 @@ void bios_map_init(struct multiboot_mmap_entry *bmmap_addr, unsigned int bmmap_l
while((unsigned int)bmmap < (unsigned int)bmmap_addr + bmmap_length) {
from_high = (unsigned int)(bmmap->addr >> 32);
from_low = (unsigned int)(bmmap->addr & 0xFFFFFFFF);
+ to_orig = (bmmap->addr + bmmap->len);
to = (bmmap->addr + bmmap->len) - 1;
to_high = (unsigned int)(to >> 32);
to_low = (unsigned int)(to & 0xFFFFFFFF);
@@ -124,6 +125,9 @@ void bios_map_init(struct multiboot_mmap_entry *bmmap_addr, unsigned int bmmap_l
to_low,
bios_mem_type[type]
);
+ /* restore the original end address */
+ to_high = (unsigned int)(to_orig >> 32);
+ to_low = (unsigned int)(to_orig & 0xFFFFFFFF);
if(n < NR_BIOS_MM_ENT && bmmap->len) {
bios_mem_map[n].from = from_low;
bios_mem_map[n].from_hi = from_high; After applying this patch, the memory map in the Fiwix kernel looks like this (same as before, nothing changed):
Then, after kexec, Linux reports:
This memory reservation is needed by the kexec implementation: Lines 308 to 313 in 3a71a2f
But you are right that this bug prevented this address to have the off-by-1 ending. Looks like this is also fixed. Additionally, there is also a bug in diff --git a/kernel/kexec.c b/kernel/kexec.c
index c35a15d..aab5ada 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -247,7 +247,7 @@ void kexec_multiboot1(void)
/* space reserved for the memory map structure */
nmaps = 0;
- while(bios_mem_map[nmaps].to) {
+ while(bios_mem_map[nmaps].type) {
nmaps++;
}
esp -= sizeof(struct multiboot_mmap_entry) * nmaps;
@@ -259,7 +259,7 @@ void kexec_multiboot1(void)
map->addr = map->addr << 32 | bios_mem_map[n].from;
map->len = bios_mem_map[n].to_hi;
map->len = map->len << 32 | bios_mem_map[n].to;
- map->len -= map->addr - 1;
+ map->len -= map->addr;
map->type = bios_mem_map[n].type;
map++;
} |
@Googulator, I've just pushed some changes in your PR #74 that merges your patch with mine. |
@Googulator, did you have an opportunity to check the final patch? |
Not yet, will do in the next few days. |
@Googulator, did you find time to check the final patch? |
With the current code in #74:
Looks to be fixed. |
Excellent, thank you. |
The following 2 excerpts are from the same live-bootstrap qemu session.
Fiwix reported the memory map as follows:
Then, after kexec, Linux reports:
Two oddities are visible:
The text was updated successfully, but these errors were encountered: