-
Notifications
You must be signed in to change notification settings - Fork 0
/
payload.c
89 lines (69 loc) · 2.29 KB
/
payload.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#define CPUID_EXT_HYPERVISOR ((unsigned int)(1 << 31))
#define LOG_PORT 42
static void outb(uint16_t port, uint8_t value) {
asm("outb %0, %1" : /* empty */ : "a" (value), "Nd" (port) : "memory");
}
static void out_string(uint16_t port, char* value) {
for (char* p = value; *p; ++p)
outb(port, *p);
}
static void out_string_max(uint16_t port, char* value, uint32_t max_len) {
for (char* p = value; *p && (p - value) < max_len; ++p)
outb(port, *p);
}
static void get_cpuid(unsigned leaf, unsigned* regs) {
asm volatile("cpuid": "=a" (regs[0]), "=b" (regs[1]),
"=c" (regs[2]), "=d" (regs[3]) : "a" (leaf));
}
static void cpu_set_msr(uint32_t msr, uint32_t lo, uint32_t hi) {
asm volatile("wrmsr" : : "a"(lo), "d"(hi), "c"(msr));
}
static void cpu_get_msr(uint32_t msr, uint32_t *lo, uint32_t *hi) {
asm volatile("rdmsr" : "=a"(*lo), "=d"(*hi) : "c"(msr));
}
static void halt(uint32_t value) {
asm("hlt" : /* empty */ : "a" (value) : "memory");
}
static inline void mmio_writeq(uint64_t val, volatile void *addr)
{
asm volatile("mov" "q" " %0, %1": :
"r" (val), "m" (*(volatile uint64_t *)addr) :"memory");
}
static inline uint64_t mmio_readq(volatile void *addr)
{
uint64_t val;
asm volatile("mov" "q" " %1, %0":
"=r" (val): "m" (*(volatile uint64_t *)addr) :"memory");
return val;
}
// .data is located in an unmapped memory area (see payload.ld),
// generating an MMIO exit when accessed
unsigned char mmio_buf[1024];
void
__attribute__((section(".start")))
_start(void) {
out_string(LOG_PORT, "Greetings from the guest!\n");
unsigned regs[] = {0, 0, 0, 0};
get_cpuid(1, regs);
if (regs[2] == CPUID_EXT_HYPERVISOR) {
out_string(LOG_PORT, "Hypervisor present\n");
}
memset(regs, 0, sizeof(regs));
get_cpuid(0x40000000, regs);
char id[13] = {0};
memcpy(id, ®s[1], 12);
id[12] = 0;
out_string(LOG_PORT, "Hypervisor ID: ");
out_string_max(LOG_PORT, id, sizeof(id));
out_string(LOG_PORT, "\n");
uint32_t lo, hi = 0;
cpu_get_msr(1, &lo, &hi);
cpu_set_msr(1, lo + 1, hi + 1);
uint64_t data = mmio_readq(mmio_buf);
mmio_writeq(data + 1, mmio_buf);
halt(0);
}