*/
#include <palacios/vm_guest.h>
+#include <palacios/vm_guest_mem.h>
#include <palacios/vmm_symcall.h>
#include <palacios/vmm_symspy.h>
#include <palacios/vmm_msr.h>
+#include <palacios/vmm_lowlevel.h>
+#include <palacios/vmm_debug.h>
// A succesfull symcall returns via the RET_HCALL, with the return values in registers
// A symcall error returns via the ERR_HCALL with the error code in rbx
state->sym_call_fs = src.value;
break;
default:
- PrintError("Invalid Symbiotic MSR write (0x%x)\n", msr);
+ PrintError(core->vm_info, core, "Invalid Symbiotic MSR write (0x%x)\n", msr);
return -1;
}
return 0;
static int sym_call_err(struct guest_info * core, uint_t hcall_id, void * private_data) {
struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_core_state.symcall_state);
- PrintError("sym call error\n");
+ PrintError(core->vm_info, core, "sym call error\n");
state->sym_call_errno = (int)core->vm_regs.rbx;
v3_print_guest_state(core);
static int sym_call_ret(struct guest_info * core, uint_t hcall_id, void * private_data) {
struct v3_symcall_state * state = (struct v3_symcall_state *)&(core->sym_core_state.symcall_state);
- // PrintError("Return from sym call (ID=%x)\n", hcall_id);
+ // PrintError(info->vm_info, info, "Return from sym call (ID=%x)\n", hcall_id);
// v3_print_guest_state(info);
state->sym_call_returned = 1;
while (state->sym_call_returned == 0) {
if (v3_vm_enter(core) == -1) {
- PrintError("Error in Sym call\n");
+ PrintError(core->vm_info, core, "Error in Sym call\n");
return -1;
}
}
}
+//
+// We don't handle those fancy 64 bit system segments...
+//
+static int translate_segment(struct guest_info * info, uint16_t selector, struct v3_segment * seg) {
+ struct v3_segment * gdt = &(info->segments.gdtr);
+ addr_t gdt_addr = 0;
+ uint16_t seg_offset = (selector & ~0x7);
+ addr_t seg_addr = 0;
+ struct gen_segment * gen_seg = NULL;
+ struct seg_selector sel;
+
+ memset(seg, 0, sizeof(struct v3_segment));
+
+ sel.value = selector;
+
+ if (sel.ti == 1) {
+ PrintError(info->vm_info, info, "LDT translations not supported\n");
+ return -1;
+ }
+
+ if (v3_gva_to_hva(info, gdt->base, &gdt_addr) == -1) {
+ PrintError(info->vm_info, info, "Unable to translate GDT address\n");
+ return -1;
+ }
+
+ seg_addr = gdt_addr + seg_offset;
+ gen_seg = (struct gen_segment *)seg_addr;
+
+ //translate
+ seg->selector = selector;
+
+ seg->limit = gen_seg->limit_hi;
+ seg->limit <<= 16;
+ seg->limit += gen_seg->limit_lo;
+
+ seg->base = gen_seg->base_hi;
+ seg->base <<= 24;
+ seg->base += gen_seg->base_lo;
+
+ if (gen_seg->granularity == 1) {
+ seg->limit <<= 12;
+ seg->limit |= 0xfff;
+ }
+
+ seg->type = gen_seg->type;
+ seg->system = gen_seg->system;
+ seg->dpl = gen_seg->dpl;
+ seg->present = gen_seg->present;
+ seg->avail = gen_seg->avail;
+ seg->long_mode = gen_seg->long_mode;
+ seg->db = gen_seg->db;
+ seg->granularity = gen_seg->granularity;
+
+ return 0;
+}
+
+
+
int v3_sym_call(struct guest_info * core,
uint64_t call_num, sym_arg_t * arg0,
sym_arg_t * arg1, sym_arg_t * arg2,
struct v3_segment sym_ss;
uint64_t trash_args[5] = { [0 ... 4] = 0 };
- // PrintDebug("Making Sym call\n");
+ // PrintDebug(core->vm_info, core, "Making Sym call\n");
// v3_print_guest_state(info);
if ((symspy_state->local_page->sym_call_enabled == 0) ||
core->rip = state->sym_call_rip;
core->vm_regs.rsp = state->sym_call_rsp; // old contest rsp is saved in vm_regs
- v3_translate_segment(core, state->sym_call_cs, &sym_cs);
+ translate_segment(core, state->sym_call_cs, &sym_cs);
memcpy(&(core->segments.cs), &sym_cs, sizeof(struct v3_segment));
- v3_translate_segment(core, state->sym_call_cs + 8, &sym_ss);
+ translate_segment(core, state->sym_call_cs + 8, &sym_ss);
memcpy(&(core->segments.ss), &sym_ss, sizeof(struct v3_segment));
core->segments.gs.base = state->sym_call_gs;
state->sym_call_active = 1;
state->sym_call_returned = 0;
- // PrintDebug("Sym state\n");
+ // PrintDebug(core->vm_info, core, "Sym state\n");
// v3_print_guest_state(core);
// Do the sym call entry
if (execute_symcall(core) == -1) {
- PrintError("SYMCALL error\n");
+ PrintError(core->vm_info, core, "SYMCALL error\n");
return -1;
}
- // PrintError("restoring guest state\n");
+ // PrintError(core->vm_info, core, "restoring guest state\n");
// v3_print_guest_state(core);
return 0;