aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest/hypercalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lguest/hypercalls.c')
-rw-r--r--drivers/lguest/hypercalls.c49
1 files changed, 23 insertions, 26 deletions
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c
index 0471018d700d..32666d0d956a 100644
--- a/drivers/lguest/hypercalls.c
+++ b/drivers/lguest/hypercalls.c
@@ -31,8 +31,6 @@
31 * Or gets killed. Or, in the case of LHCALL_CRASH, both. */ 31 * Or gets killed. Or, in the case of LHCALL_CRASH, both. */
32static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args) 32static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
33{ 33{
34 struct lguest *lg = cpu->lg;
35
36 switch (args->arg0) { 34 switch (args->arg0) {
37 case LHCALL_FLUSH_ASYNC: 35 case LHCALL_FLUSH_ASYNC:
38 /* This call does nothing, except by breaking out of the Guest 36 /* This call does nothing, except by breaking out of the Guest
@@ -41,7 +39,7 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
41 case LHCALL_LGUEST_INIT: 39 case LHCALL_LGUEST_INIT:
42 /* You can't get here unless you're already initialized. Don't 40 /* You can't get here unless you're already initialized. Don't
43 * do that. */ 41 * do that. */
44 kill_guest(lg, "already have lguest_data"); 42 kill_guest(cpu, "already have lguest_data");
45 break; 43 break;
46 case LHCALL_SHUTDOWN: { 44 case LHCALL_SHUTDOWN: {
47 /* Shutdown is such a trivial hypercall that we do it in four 45 /* Shutdown is such a trivial hypercall that we do it in four
@@ -49,11 +47,11 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
49 char msg[128]; 47 char msg[128];
50 /* If the lgread fails, it will call kill_guest() itself; the 48 /* If the lgread fails, it will call kill_guest() itself; the
51 * kill_guest() with the message will be ignored. */ 49 * kill_guest() with the message will be ignored. */
52 __lgread(lg, msg, args->arg1, sizeof(msg)); 50 __lgread(cpu, msg, args->arg1, sizeof(msg));
53 msg[sizeof(msg)-1] = '\0'; 51 msg[sizeof(msg)-1] = '\0';
54 kill_guest(lg, "CRASH: %s", msg); 52 kill_guest(cpu, "CRASH: %s", msg);
55 if (args->arg2 == LGUEST_SHUTDOWN_RESTART) 53 if (args->arg2 == LGUEST_SHUTDOWN_RESTART)
56 lg->dead = ERR_PTR(-ERESTART); 54 cpu->lg->dead = ERR_PTR(-ERESTART);
57 break; 55 break;
58 } 56 }
59 case LHCALL_FLUSH_TLB: 57 case LHCALL_FLUSH_TLB:
@@ -74,10 +72,10 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
74 guest_set_stack(cpu, args->arg1, args->arg2, args->arg3); 72 guest_set_stack(cpu, args->arg1, args->arg2, args->arg3);
75 break; 73 break;
76 case LHCALL_SET_PTE: 74 case LHCALL_SET_PTE:
77 guest_set_pte(lg, args->arg1, args->arg2, __pte(args->arg3)); 75 guest_set_pte(cpu, args->arg1, args->arg2, __pte(args->arg3));
78 break; 76 break;
79 case LHCALL_SET_PMD: 77 case LHCALL_SET_PMD:
80 guest_set_pmd(lg, args->arg1, args->arg2); 78 guest_set_pmd(cpu->lg, args->arg1, args->arg2);
81 break; 79 break;
82 case LHCALL_SET_CLOCKEVENT: 80 case LHCALL_SET_CLOCKEVENT:
83 guest_set_clockevent(cpu, args->arg1); 81 guest_set_clockevent(cpu, args->arg1);
@@ -96,7 +94,7 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
96 default: 94 default:
97 /* It should be an architecture-specific hypercall. */ 95 /* It should be an architecture-specific hypercall. */
98 if (lguest_arch_do_hcall(cpu, args)) 96 if (lguest_arch_do_hcall(cpu, args))
99 kill_guest(lg, "Bad hypercall %li\n", args->arg0); 97 kill_guest(cpu, "Bad hypercall %li\n", args->arg0);
100 } 98 }
101} 99}
102/*:*/ 100/*:*/
@@ -112,10 +110,9 @@ static void do_async_hcalls(struct lg_cpu *cpu)
112{ 110{
113 unsigned int i; 111 unsigned int i;
114 u8 st[LHCALL_RING_SIZE]; 112 u8 st[LHCALL_RING_SIZE];
115 struct lguest *lg = cpu->lg;
116 113
117 /* For simplicity, we copy the entire call status array in at once. */ 114 /* For simplicity, we copy the entire call status array in at once. */
118 if (copy_from_user(&st, &lg->lguest_data->hcall_status, sizeof(st))) 115 if (copy_from_user(&st, &cpu->lg->lguest_data->hcall_status, sizeof(st)))
119 return; 116 return;
120 117
121 /* We process "struct lguest_data"s hcalls[] ring once. */ 118 /* We process "struct lguest_data"s hcalls[] ring once. */
@@ -137,9 +134,9 @@ static void do_async_hcalls(struct lg_cpu *cpu)
137 134
138 /* Copy the hypercall arguments into a local copy of 135 /* Copy the hypercall arguments into a local copy of
139 * the hcall_args struct. */ 136 * the hcall_args struct. */
140 if (copy_from_user(&args, &lg->lguest_data->hcalls[n], 137 if (copy_from_user(&args, &cpu->lg->lguest_data->hcalls[n],
141 sizeof(struct hcall_args))) { 138 sizeof(struct hcall_args))) {
142 kill_guest(lg, "Fetching async hypercalls"); 139 kill_guest(cpu, "Fetching async hypercalls");
143 break; 140 break;
144 } 141 }
145 142
@@ -147,8 +144,8 @@ static void do_async_hcalls(struct lg_cpu *cpu)
147 do_hcall(cpu, &args); 144 do_hcall(cpu, &args);
148 145
149 /* Mark the hypercall done. */ 146 /* Mark the hypercall done. */
150 if (put_user(0xFF, &lg->lguest_data->hcall_status[n])) { 147 if (put_user(0xFF, &cpu->lg->lguest_data->hcall_status[n])) {
151 kill_guest(lg, "Writing result for async hypercall"); 148 kill_guest(cpu, "Writing result for async hypercall");
152 break; 149 break;
153 } 150 }
154 151
@@ -163,29 +160,28 @@ static void do_async_hcalls(struct lg_cpu *cpu)
163 * Guest makes a hypercall, we end up here to set things up: */ 160 * Guest makes a hypercall, we end up here to set things up: */
164static void initialize(struct lg_cpu *cpu) 161static void initialize(struct lg_cpu *cpu)
165{ 162{
166 struct lguest *lg = cpu->lg;
167 /* You can't do anything until you're initialized. The Guest knows the 163 /* You can't do anything until you're initialized. The Guest knows the
168 * rules, so we're unforgiving here. */ 164 * rules, so we're unforgiving here. */
169 if (cpu->hcall->arg0 != LHCALL_LGUEST_INIT) { 165 if (cpu->hcall->arg0 != LHCALL_LGUEST_INIT) {
170 kill_guest(lg, "hypercall %li before INIT", cpu->hcall->arg0); 166 kill_guest(cpu, "hypercall %li before INIT", cpu->hcall->arg0);
171 return; 167 return;
172 } 168 }
173 169
174 if (lguest_arch_init_hypercalls(cpu)) 170 if (lguest_arch_init_hypercalls(cpu))
175 kill_guest(lg, "bad guest page %p", lg->lguest_data); 171 kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
176 172
177 /* The Guest tells us where we're not to deliver interrupts by putting 173 /* The Guest tells us where we're not to deliver interrupts by putting
178 * the range of addresses into "struct lguest_data". */ 174 * the range of addresses into "struct lguest_data". */
179 if (get_user(lg->noirq_start, &lg->lguest_data->noirq_start) 175 if (get_user(cpu->lg->noirq_start, &cpu->lg->lguest_data->noirq_start)
180 || get_user(lg->noirq_end, &lg->lguest_data->noirq_end)) 176 || get_user(cpu->lg->noirq_end, &cpu->lg->lguest_data->noirq_end))
181 kill_guest(lg, "bad guest page %p", lg->lguest_data); 177 kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
182 178
183 /* We write the current time into the Guest's data page once so it can 179 /* We write the current time into the Guest's data page once so it can
184 * set its clock. */ 180 * set its clock. */
185 write_timestamp(lg); 181 write_timestamp(cpu);
186 182
187 /* page_tables.c will also do some setup. */ 183 /* page_tables.c will also do some setup. */
188 page_table_guest_data_init(lg); 184 page_table_guest_data_init(cpu);
189 185
190 /* This is the one case where the above accesses might have been the 186 /* This is the one case where the above accesses might have been the
191 * first write to a Guest page. This may have caused a copy-on-write 187 * first write to a Guest page. This may have caused a copy-on-write
@@ -237,10 +233,11 @@ void do_hypercalls(struct lg_cpu *cpu)
237 233
238/* This routine supplies the Guest with time: it's used for wallclock time at 234/* This routine supplies the Guest with time: it's used for wallclock time at
239 * initial boot and as a rough time source if the TSC isn't available. */ 235 * initial boot and as a rough time source if the TSC isn't available. */
240void write_timestamp(struct lguest *lg) 236void write_timestamp(struct lg_cpu *cpu)
241{ 237{
242 struct timespec now; 238 struct timespec now;
243 ktime_get_real_ts(&now); 239 ktime_get_real_ts(&now);
244 if (copy_to_user(&lg->lguest_data->time, &now, sizeof(struct timespec))) 240 if (copy_to_user(&cpu->lg->lguest_data->time,
245 kill_guest(lg, "Writing timestamp"); 241 &now, sizeof(struct timespec)))
242 kill_guest(cpu, "Writing timestamp");
246} 243}