Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenXiangShan
NEMU
提交
225bd41f
N
NEMU
项目概览
OpenXiangShan
/
NEMU
11 个月 前同步成功
通知
7
Star
171
Fork
67
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
N
NEMU
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
225bd41f
编写于
8月 05, 2019
作者:
Z
Zihao Yu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
x86: add kvm support
上级
2f1c8be6
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
214 addition
and
2 deletion
+214
-2
src/device/io/port-io.c
src/device/io/port-io.c
+2
-2
src/isa/x86/exec/exec.c
src/isa/x86/exec/exec.c
+5
-0
src/isa/x86/kvm/kvm.c
src/isa/x86/kvm/kvm.c
+207
-0
未找到文件。
src/device/io/port-io.c
浏览文件 @
225bd41f
...
...
@@ -18,14 +18,14 @@ void add_pio_map(char *name, ioaddr_t addr, uint8_t *space, int len, io_callback
nr_map
++
;
}
static
inline
uint32_t
pio_read_common
(
ioaddr_t
addr
,
int
len
)
{
uint32_t
pio_read_common
(
ioaddr_t
addr
,
int
len
)
{
assert
(
addr
+
len
-
1
<
PORT_IO_SPACE_MAX
);
int
mapid
=
find_mapid_by_addr
(
maps
,
nr_map
,
addr
);
assert
(
mapid
!=
-
1
);
return
map_read
(
addr
,
len
,
&
maps
[
mapid
]);
}
static
inline
void
pio_write_common
(
ioaddr_t
addr
,
uint32_t
data
,
int
len
)
{
void
pio_write_common
(
ioaddr_t
addr
,
uint32_t
data
,
int
len
)
{
assert
(
addr
+
len
-
1
<
PORT_IO_SPACE_MAX
);
int
mapid
=
find_mapid_by_addr
(
maps
,
nr_map
,
addr
);
assert
(
mapid
!=
-
1
);
...
...
src/isa/x86/exec/exec.c
浏览文件 @
225bd41f
...
...
@@ -193,8 +193,13 @@ static make_EHelper(2byte_esc) {
}
void
isa_exec
(
vaddr_t
*
pc
)
{
#ifdef USE_KVM
extern
void
kvm_exec
(
void
);
kvm_exec
();
#else
uint32_t
opcode
=
instr_fetch
(
pc
,
1
);
decinfo
.
opcode
=
opcode
;
set_width
(
opcode_table
[
opcode
].
width
);
idex
(
pc
,
&
opcode_table
[
opcode
]);
#endif
}
src/isa/x86/kvm/kvm.c
0 → 100644
浏览文件 @
225bd41f
#include "nemu.h"
#include "cpu/exec.h"
#include "monitor/monitor.h"
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/kvm.h>
extern
uint32_t
pio_read_common
(
ioaddr_t
addr
,
int
len
);
extern
void
pio_write_common
(
ioaddr_t
addr
,
uint32_t
data
,
int
len
);
/* CR0 bits */
#define CR0_PE 1u
struct
vm
{
int
sys_fd
;
int
fd
;
char
*
mem
;
};
void
vm_init
(
struct
vm
*
vm
,
size_t
mem_size
)
{
int
api_ver
;
struct
kvm_userspace_memory_region
memreg
;
vm
->
sys_fd
=
open
(
"/dev/kvm"
,
O_RDWR
);
if
(
vm
->
sys_fd
<
0
)
{
perror
(
"open /dev/kvm"
);
assert
(
0
);
}
api_ver
=
ioctl
(
vm
->
sys_fd
,
KVM_GET_API_VERSION
,
0
);
if
(
api_ver
<
0
)
{
perror
(
"KVM_GET_API_VERSION"
);
assert
(
0
);
}
if
(
api_ver
!=
KVM_API_VERSION
)
{
fprintf
(
stderr
,
"Got KVM api version %d, expected %d
\n
"
,
api_ver
,
KVM_API_VERSION
);
assert
(
0
);
}
vm
->
fd
=
ioctl
(
vm
->
sys_fd
,
KVM_CREATE_VM
,
0
);
if
(
vm
->
fd
<
0
)
{
perror
(
"KVM_CREATE_VM"
);
assert
(
0
);
}
if
(
ioctl
(
vm
->
fd
,
KVM_SET_TSS_ADDR
,
0xfffbd000
)
<
0
)
{
perror
(
"KVM_SET_TSS_ADDR"
);
assert
(
0
);
}
vm
->
mem
=
mmap
(
NULL
,
mem_size
,
PROT_READ
|
PROT_WRITE
,
MAP_PRIVATE
|
MAP_ANONYMOUS
|
MAP_NORESERVE
,
-
1
,
0
);
if
(
vm
->
mem
==
MAP_FAILED
)
{
perror
(
"mmap mem"
);
assert
(
0
);
}
madvise
(
vm
->
mem
,
mem_size
,
MADV_MERGEABLE
);
memreg
.
slot
=
0
;
memreg
.
flags
=
0
;
memreg
.
guest_phys_addr
=
0
;
memreg
.
memory_size
=
mem_size
;
memreg
.
userspace_addr
=
(
unsigned
long
)
vm
->
mem
;
if
(
ioctl
(
vm
->
fd
,
KVM_SET_USER_MEMORY_REGION
,
&
memreg
)
<
0
)
{
perror
(
"KVM_SET_USER_MEMORY_REGION"
);
assert
(
0
);
}
}
struct
vcpu
{
int
fd
;
struct
kvm_run
*
kvm_run
;
};
void
vcpu_init
(
struct
vm
*
vm
,
struct
vcpu
*
vcpu
)
{
int
vcpu_mmap_size
;
vcpu
->
fd
=
ioctl
(
vm
->
fd
,
KVM_CREATE_VCPU
,
0
);
if
(
vcpu
->
fd
<
0
)
{
perror
(
"KVM_CREATE_VCPU"
);
assert
(
0
);
}
vcpu_mmap_size
=
ioctl
(
vm
->
sys_fd
,
KVM_GET_VCPU_MMAP_SIZE
,
0
);
if
(
vcpu_mmap_size
<=
0
)
{
perror
(
"KVM_GET_VCPU_MMAP_SIZE"
);
assert
(
0
);
}
vcpu
->
kvm_run
=
mmap
(
NULL
,
vcpu_mmap_size
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
vcpu
->
fd
,
0
);
if
(
vcpu
->
kvm_run
==
MAP_FAILED
)
{
perror
(
"mmap kvm_run"
);
assert
(
0
);
}
}
int
run_vm
(
struct
vm
*
vm
,
struct
vcpu
*
vcpu
,
size_t
sz
)
{
struct
kvm_regs
regs
;
for
(;;)
{
if
(
ioctl
(
vcpu
->
fd
,
KVM_RUN
,
0
)
<
0
)
{
if
(
errno
==
EINTR
)
continue
;
perror
(
"KVM_RUN"
);
assert
(
0
);
}
switch
(
vcpu
->
kvm_run
->
exit_reason
)
{
case
KVM_EXIT_HLT
:
if
(
ioctl
(
vcpu
->
fd
,
KVM_GET_REGS
,
&
regs
)
<
0
)
{
perror
(
"KVM_GET_REGS"
);
assert
(
0
);
}
rtl_exit
(
NEMU_END
,
regs
.
rip
,
regs
.
rax
);
return
0
;
case
KVM_EXIT_IO
:
{
struct
kvm_run
*
p
=
vcpu
->
kvm_run
;
uint8_t
*
p_data
=
(
uint8_t
*
)
p
+
p
->
io
.
data_offset
;
if
(
p
->
io
.
direction
==
KVM_EXIT_IO_OUT
)
{
pio_write_common
(
p
->
io
.
port
,
*
(
uint32_t
*
)
p_data
,
p
->
io
.
size
);
}
else
{
// FIXME
*
(
uint32_t
*
)
p_data
=
pio_read_common
(
p
->
io
.
port
,
p
->
io
.
size
);
}
continue
;
}
/* fall through */
default:
fprintf
(
stderr
,
"Got exit_reason %d,"
" expected KVM_EXIT_HLT (%d)
\n
"
,
vcpu
->
kvm_run
->
exit_reason
,
KVM_EXIT_HLT
);
assert
(
0
);
}
}
}
static
void
setup_protected_mode
(
struct
kvm_sregs
*
sregs
)
{
struct
kvm_segment
seg
=
{
.
base
=
0
,
.
limit
=
0xffffffff
,
.
selector
=
1
<<
3
,
.
present
=
1
,
.
type
=
11
,
/* Code: execute, read, accessed */
.
dpl
=
0
,
.
db
=
1
,
.
s
=
1
,
/* Code/data */
.
l
=
0
,
.
g
=
1
,
/* 4KB granularity */
};
sregs
->
cr0
|=
CR0_PE
;
/* enter protected mode */
sregs
->
cs
=
seg
;
seg
.
type
=
3
;
/* Data: read/write, accessed */
seg
.
selector
=
2
<<
3
;
sregs
->
ds
=
sregs
->
es
=
sregs
->
fs
=
sregs
->
gs
=
sregs
->
ss
=
seg
;
}
int
run_protected_mode
(
struct
vm
*
vm
,
struct
vcpu
*
vcpu
)
{
struct
kvm_sregs
sregs
;
struct
kvm_regs
regs
;
if
(
ioctl
(
vcpu
->
fd
,
KVM_GET_SREGS
,
&
sregs
)
<
0
)
{
perror
(
"KVM_GET_SREGS"
);
assert
(
0
);
}
setup_protected_mode
(
&
sregs
);
if
(
ioctl
(
vcpu
->
fd
,
KVM_SET_SREGS
,
&
sregs
)
<
0
)
{
perror
(
"KVM_SET_SREGS"
);
assert
(
0
);
}
memset
(
&
regs
,
0
,
sizeof
(
regs
));
/* Clear all FLAGS bits, except bit 1 which is always set. */
regs
.
rflags
=
2
;
regs
.
rip
=
0
;
if
(
ioctl
(
vcpu
->
fd
,
KVM_SET_REGS
,
&
regs
)
<
0
)
{
perror
(
"KVM_SET_REGS"
);
assert
(
0
);
}
memcpy
(
vm
->
mem
,
pmem
,
PMEM_SIZE
);
return
run_vm
(
vm
,
vcpu
,
4
);
}
void
kvm_exec
()
{
struct
vm
vm
;
struct
vcpu
vcpu
;
vm_init
(
&
vm
,
PMEM_SIZE
);
vcpu_init
(
&
vm
,
&
vcpu
);
run_protected_mode
(
&
vm
,
&
vcpu
);
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录