| #include "asm/bios/types.h" |
| #include "kvm/e820.h" |
| |
| #include "kvm/bios.h" |
| |
| #include <asm/processor-flags.h> |
| |
| static inline u16 flat_to_seg16(u32 address) |
| { |
| return address >> 4; |
| } |
| |
| static inline u16 flat_to_off16(u32 address, u32 segment) |
| { |
| return address - (segment << 4); |
| } |
| |
| static inline void set_fs(u16 seg) |
| { |
| asm volatile("movw %0,%%fs" : : "rm" (seg)); |
| } |
| |
| static inline u8 rdfs8(unsigned long addr) |
| { |
| u8 v; |
| |
| asm volatile("addr32 movb %%fs:%1,%0" : "=q" (v) : "m" (*(u8 *)addr)); |
| |
| return v; |
| } |
| |
| static inline u32 rdfs32(unsigned long addr) |
| { |
| u32 v; |
| |
| asm volatile("addr32 movl %%fs:%1,%0" : "=q" (v) : "m" (*(u32 *)addr)); |
| |
| return v; |
| } |
| |
| bioscall void e820_query_map(struct biosregs *regs) |
| { |
| struct e820map *e820; |
| u32 map_size; |
| u16 fs_seg; |
| u32 ndx; |
| |
| e820 = (struct e820map *)E820_MAP_START; |
| fs_seg = flat_to_seg16(E820_MAP_START); |
| set_fs(fs_seg); |
| |
| ndx = regs->ebx; |
| |
| map_size = rdfs32(flat_to_off16((u32)&e820->nr_map, fs_seg)); |
| |
| if (ndx < map_size) { |
| u32 start; |
| unsigned int i; |
| u8 *p; |
| |
| fs_seg = flat_to_seg16(E820_MAP_START); |
| set_fs(fs_seg); |
| |
| start = (u32)&e820->map[ndx]; |
| |
| p = (void *) regs->edi; |
| |
| for (i = 0; i < sizeof(struct e820entry); i++) |
| *p++ = rdfs8(flat_to_off16(start + i, fs_seg)); |
| } |
| |
| regs->eax = SMAP; |
| regs->ecx = sizeof(struct e820entry); |
| regs->ebx = ++ndx; |
| |
| /* Clear CF to indicate success. */ |
| regs->eflags &= ~X86_EFLAGS_CF; |
| |
| if (ndx >= map_size) |
| regs->ebx = 0; /* end of map */ |
| } |