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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
/******************************************************************************
* xc_private.c
*
* Helper functions for the rest of the library.
*/
#include "xc_private.h"
int init_pfn_mapper(domid_t domid)
{
int fd = open("/dev/mem", O_RDWR);
if ( fd >= 0 )
{
(void)ioctl(fd, _IO('M', 1), (unsigned long)(domid>> 0)); /* low */
(void)ioctl(fd, _IO('M', 2), (unsigned long)(domid>>32)); /* high */
}
return fd;
}
int close_pfn_mapper(int pm_handle)
{
return close(pm_handle);
}
void *map_pfn_writeable(int pm_handle, unsigned long pfn)
{
void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
MAP_SHARED, pm_handle, pfn << PAGE_SHIFT);
if ( vaddr == MAP_FAILED )
return NULL;
return vaddr;
}
void *map_pfn_readonly(int pm_handle, unsigned long pfn)
{
void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ,
MAP_SHARED, pm_handle, pfn << PAGE_SHIFT);
if ( vaddr == MAP_FAILED )
return NULL;
return vaddr;
}
void unmap_pfn(int pm_handle, void *vaddr)
{
(void)munmap(vaddr, PAGE_SIZE);
}
#define FIRST_MMU_UPDATE 2
static int flush_mmu_updates(int xc_handle, mmu_t *mmu)
{
int err = 0;
privcmd_hypercall_t hypercall;
if ( mmu->idx == FIRST_MMU_UPDATE )
return 0;
/* The first two requests set the correct subject domain (PTS and GPS). */
mmu->updates[0].val = (unsigned long)(mmu->subject<<16) & ~0xFFFFUL;
mmu->updates[0].ptr = (unsigned long)(mmu->subject<< 0) & ~0xFFFFUL;
mmu->updates[1].val = (unsigned long)(mmu->subject>>16) & ~0xFFFFUL;
mmu->updates[1].ptr = (unsigned long)(mmu->subject>>32) & ~0xFFFFUL;
mmu->updates[0].ptr |= MMU_EXTENDED_COMMAND;
mmu->updates[0].val |= MMUEXT_SET_SUBJECTDOM_L;
mmu->updates[1].ptr |= MMU_EXTENDED_COMMAND;
mmu->updates[1].val |= MMUEXT_SET_SUBJECTDOM_H | SET_PAGETABLE_SUBJECTDOM;
hypercall.op = __HYPERVISOR_mmu_update;
hypercall.arg[0] = (unsigned long)mmu->updates;
hypercall.arg[1] = (unsigned long)mmu->idx;
if ( mlock(mmu->updates, sizeof(mmu->updates)) != 0 )
{
PERROR("Could not lock pagetable update array");
err = 1;
goto out;
}
if ( do_xen_hypercall(xc_handle, &hypercall) < 0 )
{
ERROR("Failure when submitting mmu updates");
err = 1;
}
mmu->idx = FIRST_MMU_UPDATE;
(void)munlock(mmu->updates, sizeof(mmu->updates));
out:
return err;
}
mmu_t *init_mmu_updates(int xc_handle, domid_t dom)
{
mmu_t *mmu = malloc(sizeof(mmu_t));
if ( mmu == NULL )
return mmu;
mmu->idx = FIRST_MMU_UPDATE;
mmu->subject = dom;
return mmu;
}
int add_mmu_update(int xc_handle, mmu_t *mmu,
unsigned long ptr, unsigned long val)
{
mmu->updates[mmu->idx].ptr = ptr;
mmu->updates[mmu->idx].val = val;
if ( ++mmu->idx == MAX_MMU_UPDATES )
return flush_mmu_updates(xc_handle, mmu);
return 0;
}
int finish_mmu_updates(int xc_handle, mmu_t *mmu)
{
return flush_mmu_updates(xc_handle, mmu);
}
|