2 * Jailhouse, a Linux-based partitioning hypervisor
4 * Copyright (c) Siemens AG, 2013
5 * Copyright (c) Valentine Sinitsyn, 2014
8 * Jan Kiszka <jan.kiszka@siemens.com>
9 * Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
11 * This work is licensed under the terms of the GNU GPL, version 2. See
12 * the COPYING file in the top-level directory.
15 #include <jailhouse/control.h>
16 #include <jailhouse/mmio.h>
17 #include <jailhouse/paging.h>
18 #include <jailhouse/pci.h>
19 #include <jailhouse/printk.h>
20 #include <jailhouse/string.h>
21 #include <jailhouse/types.h>
22 #include <asm/i8042.h>
23 #include <asm/ioapic.h>
24 #include <asm/iommu.h>
26 #include <asm/percpu.h>
29 /* Can be overriden in vendor-specific code if needed */
30 const u8 *vcpu_get_inst_bytes(const struct guest_paging_structures *pg_structs,
31 unsigned long pc, unsigned int *size)
32 __attribute__((weak, alias("vcpu_map_inst")));
34 const u8 *vcpu_map_inst(const struct guest_paging_structures *pg_structs,
35 unsigned long pc, unsigned int *size)
37 unsigned short bytes_avail;
42 page = paging_get_guest_pages(pg_structs, pc,
43 1, PAGE_READONLY_FLAGS);
47 /* Number of bytes available before page boundary */
48 bytes_avail = PAGE_SIZE - (pc & PAGE_OFFS_MASK);
49 if (*size > bytes_avail)
52 return &page[pc & PAGE_OFFS_MASK];
58 int vcpu_cell_init(struct cell *cell)
60 const u8 *pio_bitmap = jailhouse_cell_pio_bitmap(cell->config);
61 u32 pio_bitmap_size = cell->config->pio_bitmap_size;
62 struct vcpu_io_bitmap cell_iobm, root_cell_iobm;
63 unsigned int n, pm_timer_addr;
68 /* PM timer has to be provided */
69 if (system_config->platform_info.x86.pm_timer_address == 0)
70 return trace_error(-EINVAL);
72 err = vcpu_vendor_cell_init(cell);
76 vcpu_vendor_get_cell_io_bitmap(cell, &cell_iobm);
77 memset(cell_iobm.data, -1, cell_iobm.size);
79 for (n = 0; n < 2; n++) {
80 size = pio_bitmap_size <= PAGE_SIZE ?
81 pio_bitmap_size : PAGE_SIZE;
82 memcpy(cell_iobm.data + n * PAGE_SIZE, pio_bitmap, size);
84 pio_bitmap_size -= size;
87 /* moderate access to i8042 command register */
88 cell_iobm.data[I8042_CMD_REG / 8] |= 1 << (I8042_CMD_REG % 8);
90 if (cell != &root_cell) {
92 * Shrink PIO access of root cell corresponding to new cell's
95 vcpu_vendor_get_cell_io_bitmap(&root_cell, &root_cell_iobm);
96 pio_bitmap = jailhouse_cell_pio_bitmap(cell->config);
97 pio_bitmap_size = cell->config->pio_bitmap_size;
98 for (b = root_cell_iobm.data; pio_bitmap_size > 0;
99 b++, pio_bitmap++, pio_bitmap_size--)
103 /* permit access to the PM timer */
104 pm_timer_addr = system_config->platform_info.x86.pm_timer_address;
105 for (n = 0; n < 4; n++, pm_timer_addr++) {
107 b[pm_timer_addr / 8] &= ~(1 << (pm_timer_addr % 8));
113 void vcpu_cell_exit(struct cell *cell)
115 const u8 *root_pio_bitmap =
116 jailhouse_cell_pio_bitmap(root_cell.config);
117 const u8 *pio_bitmap = jailhouse_cell_pio_bitmap(cell->config);
118 u32 pio_bitmap_size = cell->config->pio_bitmap_size;
119 struct vcpu_io_bitmap root_cell_iobm;
122 vcpu_vendor_get_cell_io_bitmap(&root_cell, &root_cell_iobm);
124 if (root_cell.config->pio_bitmap_size < pio_bitmap_size)
125 pio_bitmap_size = root_cell.config->pio_bitmap_size;
127 for (b = root_cell_iobm.data; pio_bitmap_size > 0;
128 b++, pio_bitmap++, root_pio_bitmap++, pio_bitmap_size--)
129 *b &= *pio_bitmap | *root_pio_bitmap;
131 vcpu_vendor_cell_exit(cell);
134 void vcpu_handle_hypercall(void)
136 union registers *guest_regs = &this_cpu_data()->guest_regs;
137 unsigned long code = guest_regs->rax;
138 struct vcpu_execution_state x_state;
139 unsigned long arg_mask;
142 vcpu_skip_emulated_instruction(X86_INST_LEN_HYPERCALL);
144 vcpu_vendor_get_execution_state(&x_state);
146 long_mode = !!(x_state.efer & EFER_LMA);
147 arg_mask = long_mode ? (u64)-1 : (u32)-1;
149 if ((!long_mode && (x_state.rflags & X86_RFLAGS_VM)) ||
150 (x_state.cs & 3) != 0) {
151 guest_regs->rax = -EPERM;
155 guest_regs->rax = hypercall(code, guest_regs->rdi & arg_mask,
156 guest_regs->rsi & arg_mask);
157 if (guest_regs->rax == -ENOSYS)
158 printk("CPU %d: Unknown hypercall %d, RIP: %p\n",
160 x_state.rip - X86_INST_LEN_HYPERCALL);
162 if (code == JAILHOUSE_HC_DISABLE && guest_regs->rax == 0)
163 vcpu_deactivate_vmm();
166 bool vcpu_handle_io_access(void)
168 struct vcpu_io_intercept io;
171 vcpu_vendor_get_io_intercept(&io);
173 /* string and REP-prefixed instructions are not supported */
177 result = x86_pci_config_handler(io.port, io.in, io.size);
179 result = i8042_access_handler(io.port, io.in, io.size);
182 vcpu_skip_emulated_instruction(io.inst_len);
187 panic_printk("FATAL: Invalid PIO %s, port: %x size: %d\n",
188 io.in ? "read" : "write", io.port, io.size);
192 bool vcpu_handle_mmio_access(void)
194 union registers *guest_regs = &this_cpu_data()->guest_regs;
195 enum mmio_result result = MMIO_UNHANDLED;
196 struct mmio_access mmio = {.size = 4};
197 struct guest_paging_structures pg_structs;
198 struct vcpu_mmio_intercept intercept;
199 struct vcpu_execution_state x_state;
200 struct mmio_instruction inst;
203 vcpu_vendor_get_execution_state(&x_state);
204 vcpu_vendor_get_mmio_intercept(&intercept);
206 if (!vcpu_get_guest_paging_structs(&pg_structs))
209 inst = x86_mmio_parse(x_state.rip, &pg_structs, intercept.is_write);
210 if (!inst.inst_len || inst.access_size != 4)
213 mmio.is_write = intercept.is_write;
215 mmio.value = guest_regs->by_index[inst.reg_num];
219 mmio.address = intercept.phys_addr;
220 result = mmio_handle_access(&mmio);
222 if (result == MMIO_UNHANDLED) {
223 result = pci_mmio_access_handler(this_cell(), mmio.is_write,
224 intercept.phys_addr, &val);
228 if (result == MMIO_HANDLED) {
230 guest_regs->by_index[inst.reg_num] = mmio.value;
231 vcpu_skip_emulated_instruction(inst.inst_len);
236 /* report only unhandled access failures */
237 if (result == MMIO_UNHANDLED)
238 panic_printk("FATAL: Invalid MMIO/RAM %s, addr: %p\n",
239 intercept.is_write ? "write" : "read",
240 intercept.phys_addr);
244 bool vcpu_handle_msr_read(void)
246 struct per_cpu *cpu_data = this_cpu_data();
248 switch (cpu_data->guest_regs.rcx) {
249 case MSR_X2APIC_BASE ... MSR_X2APIC_END:
250 x2apic_handle_read();
253 set_rdmsr_value(&cpu_data->guest_regs, cpu_data->pat);
255 case MSR_IA32_MTRR_DEF_TYPE:
256 set_rdmsr_value(&cpu_data->guest_regs,
257 cpu_data->mtrr_def_type);
260 panic_printk("FATAL: Unhandled MSR read: %x\n",
261 cpu_data->guest_regs.rcx);
265 vcpu_skip_emulated_instruction(X86_INST_LEN_WRMSR);
269 bool vcpu_handle_msr_write(void)
271 struct per_cpu *cpu_data = this_cpu_data();
272 unsigned int bit_pos, pa;
275 switch (cpu_data->guest_regs.rcx) {
276 case MSR_X2APIC_BASE ... MSR_X2APIC_END:
277 if (!x2apic_handle_write())
281 val = get_wrmsr_value(&cpu_data->guest_regs);
282 for (bit_pos = 0; bit_pos < 64; bit_pos += 8) {
283 pa = (val >> bit_pos) & 0xff;
284 /* filter out reserved memory types */
285 if (pa == 2 || pa == 3 || pa > 7) {
286 printk("FATAL: Invalid PAT value: %x\n", val);
291 if (cpu_data->mtrr_def_type & MTRR_ENABLE)
292 vcpu_vendor_set_guest_pat(val);
294 case MSR_IA32_MTRR_DEF_TYPE:
296 * This only emulates the difference between MTRRs enabled
297 * and disabled. When disabled, we turn off all caching by
298 * setting the guest PAT to 0. When enabled, guest PAT +
299 * host-controlled MTRRs define the guest's memory types.
301 val = get_wrmsr_value(&cpu_data->guest_regs);
302 cpu_data->mtrr_def_type = val;
303 vcpu_vendor_set_guest_pat((val & MTRR_ENABLE) ?
307 panic_printk("FATAL: Unhandled MSR write: %x\n",
308 cpu_data->guest_regs.rcx);
312 vcpu_skip_emulated_instruction(X86_INST_LEN_WRMSR);
316 void vcpu_handle_cpuid(void)
318 static const char signature[12] = "Jailhouse";
319 union registers *guest_regs = &this_cpu_data()->guest_regs;
320 u32 function = guest_regs->rax;
322 this_cpu_data()->stats[JAILHOUSE_CPU_STAT_VMEXITS_CPUID]++;
325 case JAILHOUSE_CPUID_SIGNATURE:
326 guest_regs->rax = JAILHOUSE_CPUID_FEATURES;
327 guest_regs->rbx = *(u32 *)signature;
328 guest_regs->rcx = *(u32 *)(signature + 4);
329 guest_regs->rdx = *(u32 *)(signature + 8);
331 case JAILHOUSE_CPUID_FEATURES:
338 /* clear upper 32 bits of the involved registers */
339 guest_regs->rax &= 0xffffffff;
340 guest_regs->rbx &= 0xffffffff;
341 guest_regs->rcx &= 0xffffffff;
342 guest_regs->rdx &= 0xffffffff;
344 cpuid((u32 *)&guest_regs->rax, (u32 *)&guest_regs->rbx,
345 (u32 *)&guest_regs->rcx, (u32 *)&guest_regs->rdx);
346 if (function == 0x01)
347 guest_regs->rcx |= X86_FEATURE_HYPERVISOR;
351 vcpu_skip_emulated_instruction(X86_INST_LEN_CPUID);
354 bool vcpu_handle_xsetbv(void)
356 union registers *guest_regs = &this_cpu_data()->guest_regs;
358 this_cpu_data()->stats[JAILHOUSE_CPU_STAT_VMEXITS_XSETBV]++;
360 if (cpuid_ecx(1) & X86_FEATURE_XSAVE &&
361 guest_regs->rax & X86_XCR0_FP &&
362 (guest_regs->rax & ~cpuid_eax(0x0d)) == 0 &&
363 guest_regs->rcx == 0 && guest_regs->rdx == 0) {
364 vcpu_skip_emulated_instruction(X86_INST_LEN_XSETBV);
368 : "a" (guest_regs->rax), "c" (0), "d" (0));
371 panic_printk("FATAL: Invalid xsetbv parameters: xcr[%d] = %08x:%08x\n",
372 guest_regs->rcx, guest_regs->rdx, guest_regs->rax);
376 void vcpu_reset(bool hard_reset)
378 struct per_cpu *cpu_data = this_cpu_data();
380 memset(&cpu_data->guest_regs, 0, sizeof(cpu_data->guest_regs));
383 cpu_data->pat = PAT_RESET_VALUE;
384 cpu_data->mtrr_def_type = 0;
385 vcpu_vendor_set_guest_pat(0);