diff --git a/bios/bios-rom.S b/bios/bios-rom.S index 0a8e695..0119c11 100644 --- a/bios/bios-rom.S +++ b/bios/bios-rom.S @@ -79,9 +79,6 @@ ENTRY(bios_int15) pushl %ebx pushl %eax - xor %ax, %ax - mov %ax, %fs - movl %esp, %eax call e820_query_map diff --git a/bios/e820.c b/bios/e820.c index 8d8b1c7..7f3f86f 100644 --- a/bios/e820.c +++ b/bios/e820.c @@ -1,8 +1,14 @@ #include "kvm/e820.h" +#include "kvm/segment.h" #include "kvm/bios.h" #include "kvm/util.h" +static inline void set_fs(uint16_t seg) +{ + asm volatile("movw %0,%%fs" : : "rm" (seg)); +} + static inline uint8_t rdfs8(unsigned long addr) { uint8_t v; @@ -15,23 +21,30 @@ static inline uint8_t rdfs8(unsigned long addr) void e820_query_map(struct e820_query *query) { uint8_t map_size; + uint16_t fs_seg; uint32_t ndx; + fs_seg = flat_to_seg16(E820_MAP_SIZE); + set_fs(fs_seg); + ndx = query->ebx; - map_size = rdfs8(E820_MAP_SIZE); + map_size = rdfs8(flat_to_off16(E820_MAP_SIZE, fs_seg)); if (ndx < map_size) { unsigned long start; unsigned int i; uint8_t *p; + fs_seg = flat_to_seg16(E820_MAP_START); + set_fs(fs_seg); + start = E820_MAP_START + sizeof(struct e820_entry) * ndx; p = (void *) query->edi; for (i = 0; i < sizeof(struct e820_entry); i++) - *p++ = rdfs8(start + i); + *p++ = rdfs8(flat_to_off16(start + i, fs_seg)); } query->eax = SMAP; diff --git a/include/kvm/segment.h b/include/kvm/segment.h new file mode 100644 index 0000000..0701cd7 --- /dev/null +++ b/include/kvm/segment.h @@ -0,0 +1,16 @@ +#ifndef KVM_SEGMENT_H +#define KVM_SEGMENT_H + +#include + +static inline uint16_t flat_to_seg16(uint32_t address) +{ + return address >> 4; +} + +static inline uint16_t flat_to_off16(uint32_t address, uint32_t segment) +{ + return address - (segment << 4); +} + +#endif /* KVM_SEGMENT_H */