/* This is the write (copy into Guest) version. */ void __lgwrite(struct lg_cpu *cpu, unsigned long addr, const void *b, unsigned bytes) { if (!lguest_address_ok(cpu->lg, addr, bytes) || copy_to_user(cpu->lg->mem_base + addr, b, bytes) != 0) kill_guest(cpu, "bad write address %#lx len %u", addr, bytes); }
/* * This routine copies memory from the Guest. Here we can see how useful the * kill_lguest() routine we met in the Launcher can be: we return a random * value (all zeroes) instead of needing to return an error. */ void __lgread(struct lg_cpu *cpu, void *b, unsigned long addr, unsigned bytes) { if (!lguest_address_ok(cpu->lg, addr, bytes) || copy_from_user(b, cpu->lg->mem_base + addr, bytes) != 0) { /* copy_from_user should do this, but as we rely on it... */ memset(b, 0, bytes); kill_guest(cpu, "bad read address %#lx len %u", addr, bytes); } }
/*H:126 i386-specific hypercall initialization: */ int lguest_arch_init_hypercalls(struct lg_cpu *cpu) { u32 tsc_speed; /* * The pointer to the Guest's "struct lguest_data" is the only argument. * We check that address now. */ if (!lguest_address_ok(cpu->lg, cpu->hcall->arg1, sizeof(*cpu->lg->lguest_data))) return -EFAULT; /* * Having checked it, we simply set lg->lguest_data to point straight * into the Launcher's memory at the right place and then use * copy_to_user/from_user from now on, instead of lgread/write. I put * this in to show that I'm not immune to writing stupid * optimizations. */ cpu->lg->lguest_data = cpu->lg->mem_base + cpu->hcall->arg1; /* * We insist that the Time Stamp Counter exist and doesn't change with * cpu frequency. Some devious chip manufacturers decided that TSC * changes could be handled in software. I decided that time going * backwards might be good for benchmarks, but it's bad for users. * * We also insist that the TSC be stable: the kernel detects unreliable * TSCs for its own purposes, and we use that here. */ if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && !check_tsc_unstable()) tsc_speed = tsc_khz; else tsc_speed = 0; if (put_user(tsc_speed, &cpu->lg->lguest_data->tsc_khz)) return -EFAULT; /* The interrupt code might not like the system call vector. */ if (!check_syscall_vector(cpu->lg)) kill_guest(cpu, "bad syscall vector"); return 0; }
int lguest_arch_init_hypercalls(struct lg_cpu *cpu) { u32 tsc_speed; if (!lguest_address_ok(cpu->lg, cpu->hcall->arg1, sizeof(*cpu->lg->lguest_data))) return -EFAULT; cpu->lg->lguest_data = cpu->lg->mem_base + cpu->hcall->arg1; if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) && !check_tsc_unstable()) tsc_speed = tsc_khz; else tsc_speed = 0; if (put_user(tsc_speed, &cpu->lg->lguest_data->tsc_khz)) return -EFAULT; if (!check_syscall_vector(cpu->lg)) kill_guest(cpu, "bad syscall vector"); return 0; }