Skip to content

Commit 88758df

Browse files
JasonChenCJlijinxia
authored andcommitted
add copy_from_gva/copy_to_gva functions
there are data transfer between guest virtual space(GVA) & hv(HVA), for example, guest rip fetching during instruction decoding. GVA is address continuous, but its GPA could be only 4K page address continuous, this patch adds copy_from_gva & copy_to_gva functions by doing page walking of GVA to avoid address breaking during accessing GVA. v2: - modify API interface based on new gva2gpa function, err_code added - combine similar code with inline function _copy_gpa - change API name from vcopy_from/to_vm to copy_from/to_gva Signed-off-by: Jason Chen CJ <jason.cj.chen@intel.com>
1 parent 6be8283 commit 88758df

File tree

2 files changed

+120
-65
lines changed

2 files changed

+120
-65
lines changed

hypervisor/arch/x86/guest/guest.c

Lines changed: 116 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -102,70 +102,6 @@ inline bool vm_lapic_disabled(struct vm *vm)
102102
return true;
103103
}
104104

105-
/* Caller(Guest) should make sure gpa is continuous.
106-
* - gpa from hypercall input which from kernel stack is gpa continous, not
107-
* support kernel stack from vmap
108-
* - some other gpa from hypercall parameters, VHM should make sure it's
109-
* continous
110-
*/
111-
int copy_from_vm(struct vm *vm, void *h_ptr, uint64_t gpa, uint32_t size)
112-
{
113-
uint64_t hpa;
114-
uint32_t off_in_pg, len, pg_size;
115-
void *g_ptr;
116-
117-
do {
118-
hpa = _gpa2hpa(vm, gpa, &pg_size);
119-
if (pg_size == 0) {
120-
ASSERT(0, "copy_from_vm: GPA2HPA not found");
121-
return -EINVAL;
122-
}
123-
124-
off_in_pg = gpa & (pg_size - 1);
125-
if (size > pg_size - off_in_pg)
126-
len = pg_size - off_in_pg;
127-
else
128-
len = size;
129-
130-
g_ptr = HPA2HVA(hpa);
131-
memcpy_s(h_ptr, len, g_ptr, len);
132-
gpa += len;
133-
h_ptr += len;
134-
size -= len;
135-
} while (size > 0);
136-
137-
return 0;
138-
}
139-
140-
int copy_to_vm(struct vm *vm, void *h_ptr, uint64_t gpa, uint32_t size)
141-
{
142-
uint64_t hpa;
143-
uint32_t off_in_pg, len, pg_size;
144-
void *g_ptr;
145-
146-
do {
147-
hpa = _gpa2hpa(vm, gpa, &pg_size);
148-
if (pg_size == 0) {
149-
ASSERT(0, "copy_to_vm: GPA2HPA not found");
150-
return -EINVAL;
151-
}
152-
153-
off_in_pg = gpa & (pg_size - 1);
154-
if (size > pg_size - off_in_pg)
155-
len = pg_size - off_in_pg;
156-
else
157-
len = size;
158-
159-
g_ptr = HPA2HVA(hpa);
160-
memcpy_s(g_ptr, len, h_ptr, len);
161-
gpa += len;
162-
h_ptr += len;
163-
size -= len;
164-
} while (size > 0);
165-
166-
return 0;
167-
}
168-
169105
enum vm_paging_mode get_vcpu_paging_mode(struct vcpu *vcpu)
170106
{
171107
struct run_context *cur_context =
@@ -291,7 +227,6 @@ static int _gva2gpa_pae(struct vcpu *vcpu, struct page_walk_info *pw_info,
291227

292228
out:
293229
return ret;
294-
295230
}
296231

297232
/* Refer to SDM Vol.3A 6-39 section 6.15 for the format of paging fault error
@@ -358,6 +293,122 @@ int gva2gpa(struct vcpu *vcpu, uint64_t gva, uint64_t *gpa,
358293
return ret;
359294
}
360295

296+
static inline int32_t _copy_gpa(struct vm *vm, void *h_ptr, uint64_t gpa,
297+
uint32_t size, uint32_t fix_pg_size, bool cp_from_vm)
298+
{
299+
uint64_t hpa;
300+
uint32_t off_in_pg, len, pg_size;
301+
void *g_ptr;
302+
303+
hpa = _gpa2hpa(vm, gpa, &pg_size);
304+
if (pg_size == 0) {
305+
pr_err("GPA2HPA not found");
306+
return -EINVAL;
307+
}
308+
309+
if (fix_pg_size)
310+
pg_size = fix_pg_size;
311+
312+
off_in_pg = gpa & (pg_size - 1);
313+
len = (size > pg_size - off_in_pg) ?
314+
(pg_size - off_in_pg) : size;
315+
316+
g_ptr = HPA2HVA(hpa);
317+
318+
if (cp_from_vm)
319+
memcpy_s(h_ptr, len, g_ptr, len);
320+
else
321+
memcpy_s(g_ptr, len, h_ptr, len);
322+
323+
return len;
324+
}
325+
326+
static inline int copy_gpa(struct vm *vm, void *h_ptr, uint64_t gpa,
327+
uint32_t size, bool cp_from_vm)
328+
{
329+
int32_t len;
330+
331+
if (vm == NULL) {
332+
pr_err("guest phy addr copy need vm param");
333+
return -EINVAL;
334+
}
335+
336+
do {
337+
len = _copy_gpa(vm, h_ptr, gpa, size, 0, cp_from_vm);
338+
if (len < 0)
339+
return len;
340+
341+
gpa += len;
342+
h_ptr += len;
343+
size -= len;
344+
} while (size > 0);
345+
346+
return 0;
347+
}
348+
349+
static inline int copy_gva(struct vcpu *vcpu, void *h_ptr, uint64_t gva,
350+
uint32_t size, uint32_t *err_code, bool cp_from_vm)
351+
{
352+
uint64_t gpa = 0;
353+
int32_t len, ret;
354+
355+
if (vcpu == NULL) {
356+
pr_err("guest virt addr copy need vcpu param");
357+
return -EINVAL;
358+
}
359+
if (err_code == NULL) {
360+
pr_err("guest virt addr copy need err_code param");
361+
return -EINVAL;
362+
}
363+
364+
do {
365+
ret = gva2gpa(vcpu, gva, &gpa, err_code);
366+
if (ret < 0) {
367+
pr_err("error[%d] in GVA2GPA, err_code=0x%x",
368+
ret, *err_code);
369+
return ret;
370+
}
371+
372+
len = ret = _copy_gpa(vcpu->vm, h_ptr, gpa, size,
373+
PAGE_SIZE_4K, cp_from_vm);
374+
if (ret < 0)
375+
return ret;
376+
377+
gva += len;
378+
h_ptr += len;
379+
size -= len;
380+
} while (size > 0);
381+
382+
return 0;
383+
}
384+
385+
/* Caller(Guest) should make sure gpa is continuous.
386+
* - gpa from hypercall input which from kernel stack is gpa continuous, not
387+
* support kernel stack from vmap
388+
* - some other gpa from hypercall parameters, VHM should make sure it's
389+
* continuous
390+
*/
391+
int copy_from_vm(struct vm *vm, void *h_ptr, uint64_t gpa, uint32_t size)
392+
{
393+
return copy_gpa(vm, h_ptr, gpa, size, 1);
394+
}
395+
396+
int copy_to_vm(struct vm *vm, void *h_ptr, uint64_t gpa, uint32_t size)
397+
{
398+
return copy_gpa(vm, h_ptr, gpa, size, 0);
399+
}
400+
401+
int copy_from_gva(struct vcpu *vcpu, void *h_ptr, uint64_t gva,
402+
uint32_t size, uint32_t *err_code)
403+
{
404+
return copy_gva(vcpu, h_ptr, gva, size, err_code, 1);
405+
}
406+
407+
int copy_to_gva(struct vcpu *vcpu, void *h_ptr, uint64_t gva,
408+
uint32_t size, uint32_t *err_code)
409+
{
410+
return copy_gva(vcpu, h_ptr, gva, size, err_code, 0);
411+
}
361412

362413
void init_e820(void)
363414
{

hypervisor/include/arch/x86/guest/guest.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ extern vm_sw_loader_t vm_sw_loader;
124124

125125
int copy_from_vm(struct vm *vm, void *h_ptr, uint64_t gpa, uint32_t size);
126126
int copy_to_vm(struct vm *vm, void *h_ptr, uint64_t gpa, uint32_t size);
127+
int copy_from_gva(struct vcpu *vcpu, void *h_ptr, uint64_t gva,
128+
uint32_t size, uint32_t *err_code);
129+
int copy_to_gva(struct vcpu *vcpu, void *h_ptr, uint64_t gva,
130+
uint32_t size, uint32_t *err_code);
127131

128132
uint32_t create_guest_init_gdt(struct vm *vm, uint32_t *limit);
129133
#endif /* !ASSEMBLER */

0 commit comments

Comments
 (0)