Skip to content

Commit 6a9825c

Browse files
committed
Provide modifiable per-vCPU struct in GS
1 parent efd2253 commit 6a9825c

File tree

9 files changed

+125
-29
lines changed

9 files changed

+125
-29
lines changed

guest/tests/test.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,16 @@ int test_loop()
106106
{
107107
while(1);
108108
}
109+
110+
asm(".global vcpuid\n"
111+
".type vcpuid, @function\n"
112+
"vcpuid:\n"
113+
" mov %gs:(0x0), %eax\n"
114+
" ret\n");
115+
extern int vcpuid();
116+
117+
__attribute__((used))
118+
int test_vcpu()
119+
{
120+
return vcpuid();
121+
}

lib/tinykvm/amd64/builtin/usercode.asm

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,31 @@ ALIGN 0x10
3939
out 0, eax
4040
jmp .vm64_rexit_retry
4141

42-
.vm64_cpuid:
42+
43+
%macro vcputable 1
44+
dd %1
45+
dd 0
4346
dd 0
44-
dd 1
45-
dd 2
46-
dd 3
47-
dd 4
48-
dd 5
49-
dd 6
50-
dd 7
51-
dd 8
52-
dd 9
53-
dd 10
54-
dd 11
55-
dd 12
56-
dd 13
57-
dd 14
58-
dd 15
59-
dd 16
47+
dd 0
48+
%endmacro
49+
50+
ALIGN 0x8
51+
.vm64_cpuid:
52+
vcputable 0
53+
vcputable 1
54+
vcputable 2
55+
vcputable 3
56+
vcputable 4
57+
vcputable 5
58+
vcputable 6
59+
vcputable 7
60+
vcputable 8
61+
vcputable 9
62+
vcputable 10
63+
vcputable 11
64+
vcputable 12
65+
vcputable 13
66+
vcputable 14
67+
vcputable 15
68+
vcputable 16
6069
.vm64_cpuid_end:

lib/tinykvm/amd64/usercode.cpp

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,34 @@
44
namespace tinykvm {
55

66
static const unsigned char usercode[] = {
7-
0x10, 0x00, 0x20, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x00, 0x00,
7+
0x10, 0x00, 0x20, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x40, 0x00, 0x00, 0x00,
88
0x90, 0x90, 0x90, 0x90, 0x49, 0x89, 0xcd, 0xb8, 0x77, 0xf7, 0x01, 0x00,
99
0x0f, 0x05, 0x4c, 0x89, 0xe9, 0x41, 0xff, 0xe7, 0x49, 0x89, 0xcd, 0xb8,
1010
0x07, 0xf7, 0x01, 0x00, 0x0f, 0x05, 0x4c, 0x89, 0xe9, 0x41, 0xff, 0xe7,
1111
0x48, 0x89, 0xc7, 0xb8, 0xff, 0xff, 0x00, 0x00, 0xe7, 0x00, 0xeb, 0xf7,
12-
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
13-
0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
14-
0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
15-
0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
16-
0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
17-
0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00
12+
0x90, 0x90, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
14+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
15+
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
16+
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
17+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
18+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19+
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20+
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
22+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23+
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
24+
0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
26+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27+
0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28+
0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
30+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31+
0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32+
0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
34+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1835
};
1936

2037
const user_asm_header &usercode_header()

lib/tinykvm/common.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,11 @@ namespace tinykvm
8383

8484
template<class T>
8585
struct is_stdstring : public std::is_same<T, std::basic_string<char>> {};
86+
87+
struct PerVCPUTable {
88+
int cpuid;
89+
int userval1;
90+
int userval2;
91+
int userval3;
92+
};
8693
}

lib/tinykvm/machine_utils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include "machine.hpp"
22

33
#include <cstring>
4-
#define USERMODE_FLAGS (3UL << 1 | 1UL << 63) /* USER, READ/WRITE, NX */
4+
#define USERMODE_FLAGS (0x7 | 1UL << 63) /* USER, READ/WRITE, PRESENT, NX */
55

66
namespace tinykvm {
77
static constexpr uint64_t PageMask() {

lib/tinykvm/vcpu.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ void vCPU::init(int id, Machine& machine)
112112
master_sregs.efer =
113113
EFER_SCE | EFER_LME | EFER_LMA | EFER_NXE;
114114
setup_amd64_segment_regs(master_sregs, physbase + GDT_ADDR);
115-
master_sregs.gs.base = usercode_header().translated_vm_cpuid(machine.main_memory());
115+
master_sregs.gs.base = this->vcpu_table_addr();
116116
setup_amd64_tss_regs(master_sregs, physbase + TSS_ADDR);
117117
setup_amd64_exception_regs(master_sregs, physbase + IDT_ADDR);
118118
this->set_special_registers(master_sregs);
@@ -221,7 +221,7 @@ void vCPU::smp_init(int id, Machine& machine)
221221
/* XXX: Is this correct? */
222222
sregs = machine.vcpu.get_special_registers();
223223
sregs.tr.base = memory.physbase + TSS_SMP_ADDR + (id - 1) * 104; /* AMD64_TSS */
224-
sregs.gs.base = usercode_header().translated_vm_cpuid(memory) + 4 * id;
224+
sregs.gs.base = this->vcpu_table_addr();
225225
/* XXX: Is this correct? */
226226
sregs.cr3 = memory.page_tables;
227227
sregs.cr0 &= ~CR0_WP; // XXX: Fix me!
@@ -340,6 +340,24 @@ void Machine::set_tls_base(__u64 baseaddr)
340340
vcpu.set_special_registers(sregs);
341341
}
342342

343+
uint64_t vCPU::vcpu_table_addr() const noexcept
344+
{
345+
return usercode_header().translated_vm_cpuid(machine().memory)
346+
+ sizeof(PerVCPUTable) * this->cpu_id;
347+
}
348+
void vCPU::set_vcpu_table_at(unsigned index, int value)
349+
{
350+
if (index >= 4)
351+
throw MachineException("Invalid vCPU table index", index);
352+
/* The per-vCPU data area is in the usercode area. */
353+
const auto addr = this->vcpu_table_addr() + index * 4;
354+
auto* page = machine().main_memory().get_userpage_at(addr & ~0xFFFL);
355+
if (page != nullptr) {
356+
auto offset = addr & 0xFFFL;
357+
*((int *)&page[offset]) = value;
358+
}
359+
}
360+
343361
void Machine::prepare_copy_on_write(size_t max_work_mem, uint64_t shared_memory_boundary)
344362
{
345363
assert(this->m_prepped == false);

lib/tinykvm/vcpu.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ namespace tinykvm
3030
unsigned exception_extra_offset(uint8_t intr);
3131
void decrement_smp_count();
3232

33-
auto &machine() { return *m_machine; }
34-
const auto &machine() const { return *m_machine; }
33+
auto& machine() { return *m_machine; }
34+
const auto& machine() const { return *m_machine; }
35+
36+
void set_vcpu_table_at(unsigned index, int value);
3537

3638
int fd = 0;
3739
int cpu_id = 0;
@@ -43,6 +45,8 @@ namespace tinykvm
4345
private:
4446
struct kvm_run* kvm_run = nullptr;
4547
Machine* m_machine = nullptr;
48+
49+
uint64_t vcpu_table_addr() const noexcept;
4650
};
4751

4852
} // namespace tinykvm

lib/tinykvm/vcpu_run.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,10 @@ void vCPU::print_registers() const
285285
"SS: 0x%X CS: 0x%X DS: 0x%X FS: 0x%X GS: 0x%X\n",
286286
sregs.ss.selector, sregs.cs.selector, sregs.ds.selector, sregs.fs.selector, sregs.gs.selector);
287287

288+
PRINTER(printer, buffer,
289+
"FS BASE: 0x%llX GS BASE: 0x%llX\n",
290+
sregs.fs.base, sregs.gs.base);
291+
288292
#if 0
289293
PRINTER(printer, buffer,
290294
"CR0 PE=%llu MP=%llu EM=%llu\n",

src/tests.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ std::vector<uint8_t> load_file(const std::string& filename);
1313
static void test_master_vm(tinykvm::Machine&);
1414
static void test_forking(tinykvm::Machine&);
1515
static void test_copy_on_write(tinykvm::Machine&);
16+
static void test_vcpu(tinykvm::Machine&);
1617

1718
static void verify_exists(tinykvm::Machine& vm, const char* name)
1819
{
@@ -53,6 +54,7 @@ int main(int argc, char** argv)
5354
verify_exists(master_vm, "write_value");
5455
verify_exists(master_vm, "test_is_value");
5556
verify_exists(master_vm, "test_loop");
57+
verify_exists(master_vm, "test_vcpu");
5658

5759
/* Remote debugger session */
5860
if (getenv("DEBUG"))
@@ -106,6 +108,12 @@ int main(int argc, char** argv)
106108
test_master_vm(master_vm);
107109
printf("*** Master VM OK\n");
108110

111+
printf("--- Beginning VM vCPU tests ---\n");
112+
for (size_t i = 0; i < 100; i++) {
113+
test_vcpu(master_vm);
114+
}
115+
printf("*** VM vCPU OK\n");
116+
109117
/* Make the master VM able to mass-produce copies.
110118
Make room for 16 CoW-pages enabling usage afterwards. */
111119
master_vm.prepare_copy_on_write(65536);
@@ -310,3 +318,19 @@ void test_copy_on_write(tinykvm::Machine& master_vm)
310318
*must* be supported. */
311319
}
312320
}
321+
322+
void test_vcpu(tinykvm::Machine& master_vm)
323+
{
324+
for (size_t i = 0; i < 10; i++)
325+
{
326+
try {
327+
master_vm.cpu().set_vcpu_table_at(0, i);
328+
master_vm.vmcall("test_vcpu");
329+
KASSERT(master_vm.return_value() == i);
330+
} catch (...) {
331+
//master_vm.print_pagetables();
332+
master_vm.print_registers();
333+
throw;
334+
}
335+
}
336+
}

0 commit comments

Comments
 (0)