mirror of
https://github.com/clearlinux/kvmtool.git
synced 2026-08-28 09:55:57 +00:00
kvm: Use proper segment + offset in e820 bios
This patch fixes E820 BIOS emulation on AMD CPUs that, unlike Intel ones, require proper 16-bit segment/offset addressing in virtualized 16-bit mode. Reported-by: Asias He <asias.hejun@gmail.com> Tested-by: Asias He <asias.hejun@gmail.com> Acked-by: Cyrill Gorcunov <gorcunov@gmail.com> Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
This commit is contained in:
committed by
Will Deacon
parent
c89b656f19
commit
c2d4a49fa4
@@ -79,9 +79,6 @@ ENTRY(bios_int15)
|
||||
pushl %ebx
|
||||
pushl %eax
|
||||
|
||||
xor %ax, %ax
|
||||
mov %ax, %fs
|
||||
|
||||
movl %esp, %eax
|
||||
call e820_query_map
|
||||
|
||||
|
||||
+15
-2
@@ -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;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef KVM_SEGMENT_H
|
||||
#define KVM_SEGMENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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 */
|
||||
Reference in New Issue
Block a user