diff options
author | Xiantao Zhang <xiantao.zhang@intel.com> | 2009-01-20 22:21:27 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-03-24 05:03:06 -0400 |
commit | 7d656bd996b68737d5d07643bc57311059038d67 (patch) | |
tree | 674c9d3910547c1185785a7c827e54e2425f9fd8 /arch/ia64/kvm | |
parent | 4b7bb626e3133eab131328a0770864b322c1bfe6 (diff) |
KVM: ia64: Implement some pal calls needed for windows 2008
For windows 2008, it needs more pal calls to implement for booting.
In addition, also changes the name of set_{sal, pal}_call_result to
get_{sal,pal}_call_result for readability.
Signed-off-by: Xiantao Zhang <xiantao.zhang@intel.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/ia64/kvm')
-rw-r--r-- | arch/ia64/kvm/kvm_fw.c | 151 | ||||
-rw-r--r-- | arch/ia64/kvm/process.c | 8 |
2 files changed, 152 insertions, 7 deletions
diff --git a/arch/ia64/kvm/kvm_fw.c b/arch/ia64/kvm/kvm_fw.c index cb7600bdff9d..a8ae52ed5635 100644 --- a/arch/ia64/kvm/kvm_fw.c +++ b/arch/ia64/kvm/kvm_fw.c | |||
@@ -227,6 +227,18 @@ static struct ia64_pal_retval pal_proc_get_features(struct kvm_vcpu *vcpu) | |||
227 | return result; | 227 | return result; |
228 | } | 228 | } |
229 | 229 | ||
230 | static struct ia64_pal_retval pal_register_info(struct kvm_vcpu *vcpu) | ||
231 | { | ||
232 | |||
233 | struct ia64_pal_retval result = {0, 0, 0, 0}; | ||
234 | long in0, in1, in2, in3; | ||
235 | |||
236 | kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3); | ||
237 | result.status = ia64_pal_register_info(in1, &result.v1, &result.v2); | ||
238 | |||
239 | return result; | ||
240 | } | ||
241 | |||
230 | static struct ia64_pal_retval pal_cache_info(struct kvm_vcpu *vcpu) | 242 | static struct ia64_pal_retval pal_cache_info(struct kvm_vcpu *vcpu) |
231 | { | 243 | { |
232 | 244 | ||
@@ -268,8 +280,12 @@ static struct ia64_pal_retval pal_vm_summary(struct kvm_vcpu *vcpu) | |||
268 | static struct ia64_pal_retval pal_vm_info(struct kvm_vcpu *vcpu) | 280 | static struct ia64_pal_retval pal_vm_info(struct kvm_vcpu *vcpu) |
269 | { | 281 | { |
270 | struct ia64_pal_retval result; | 282 | struct ia64_pal_retval result; |
283 | unsigned long in0, in1, in2, in3; | ||
271 | 284 | ||
272 | INIT_PAL_STATUS_UNIMPLEMENTED(result); | 285 | kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3); |
286 | |||
287 | result.status = ia64_pal_vm_info(in1, in2, | ||
288 | (pal_tc_info_u_t *)&result.v1, &result.v2); | ||
273 | 289 | ||
274 | return result; | 290 | return result; |
275 | } | 291 | } |
@@ -292,6 +308,108 @@ static void prepare_for_halt(struct kvm_vcpu *vcpu) | |||
292 | vcpu->arch.timer_fired = 0; | 308 | vcpu->arch.timer_fired = 0; |
293 | } | 309 | } |
294 | 310 | ||
311 | static struct ia64_pal_retval pal_perf_mon_info(struct kvm_vcpu *vcpu) | ||
312 | { | ||
313 | long status; | ||
314 | unsigned long in0, in1, in2, in3, r9; | ||
315 | unsigned long pm_buffer[16]; | ||
316 | |||
317 | kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3); | ||
318 | status = ia64_pal_perf_mon_info(pm_buffer, | ||
319 | (pal_perf_mon_info_u_t *) &r9); | ||
320 | if (status != 0) { | ||
321 | printk(KERN_DEBUG"PAL_PERF_MON_INFO fails ret=%ld\n", status); | ||
322 | } else { | ||
323 | if (in1) | ||
324 | memcpy((void *)in1, pm_buffer, sizeof(pm_buffer)); | ||
325 | else { | ||
326 | status = PAL_STATUS_EINVAL; | ||
327 | printk(KERN_WARNING"Invalid parameters " | ||
328 | "for PAL call:0x%lx!\n", in0); | ||
329 | } | ||
330 | } | ||
331 | return (struct ia64_pal_retval){status, r9, 0, 0}; | ||
332 | } | ||
333 | |||
334 | static struct ia64_pal_retval pal_halt_info(struct kvm_vcpu *vcpu) | ||
335 | { | ||
336 | unsigned long in0, in1, in2, in3; | ||
337 | long status; | ||
338 | unsigned long res = 1000UL | (1000UL << 16) | (10UL << 32) | ||
339 | | (1UL << 61) | (1UL << 60); | ||
340 | |||
341 | kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3); | ||
342 | if (in1) { | ||
343 | memcpy((void *)in1, &res, sizeof(res)); | ||
344 | status = 0; | ||
345 | } else{ | ||
346 | status = PAL_STATUS_EINVAL; | ||
347 | printk(KERN_WARNING"Invalid parameters " | ||
348 | "for PAL call:0x%lx!\n", in0); | ||
349 | } | ||
350 | |||
351 | return (struct ia64_pal_retval){status, 0, 0, 0}; | ||
352 | } | ||
353 | |||
354 | static struct ia64_pal_retval pal_mem_attrib(struct kvm_vcpu *vcpu) | ||
355 | { | ||
356 | unsigned long r9; | ||
357 | long status; | ||
358 | |||
359 | status = ia64_pal_mem_attrib(&r9); | ||
360 | |||
361 | return (struct ia64_pal_retval){status, r9, 0, 0}; | ||
362 | } | ||
363 | |||
364 | static void remote_pal_prefetch_visibility(void *v) | ||
365 | { | ||
366 | s64 trans_type = (s64)v; | ||
367 | ia64_pal_prefetch_visibility(trans_type); | ||
368 | } | ||
369 | |||
370 | static struct ia64_pal_retval pal_prefetch_visibility(struct kvm_vcpu *vcpu) | ||
371 | { | ||
372 | struct ia64_pal_retval result = {0, 0, 0, 0}; | ||
373 | unsigned long in0, in1, in2, in3; | ||
374 | kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3); | ||
375 | result.status = ia64_pal_prefetch_visibility(in1); | ||
376 | if (result.status == 0) { | ||
377 | /* Must be performed on all remote processors | ||
378 | in the coherence domain. */ | ||
379 | smp_call_function(remote_pal_prefetch_visibility, | ||
380 | (void *)in1, 1); | ||
381 | /* Unnecessary on remote processor for other vcpus!*/ | ||
382 | result.status = 1; | ||
383 | } | ||
384 | return result; | ||
385 | } | ||
386 | |||
387 | static void remote_pal_mc_drain(void *v) | ||
388 | { | ||
389 | ia64_pal_mc_drain(); | ||
390 | } | ||
391 | |||
392 | static struct ia64_pal_retval pal_get_brand_info(struct kvm_vcpu *vcpu) | ||
393 | { | ||
394 | struct ia64_pal_retval result = {0, 0, 0, 0}; | ||
395 | unsigned long in0, in1, in2, in3; | ||
396 | |||
397 | kvm_get_pal_call_data(vcpu, &in0, &in1, &in2, &in3); | ||
398 | |||
399 | if (in1 == 0 && in2) { | ||
400 | char brand_info[128]; | ||
401 | result.status = ia64_pal_get_brand_info(brand_info); | ||
402 | if (result.status == PAL_STATUS_SUCCESS) | ||
403 | memcpy((void *)in2, brand_info, 128); | ||
404 | } else { | ||
405 | result.status = PAL_STATUS_REQUIRES_MEMORY; | ||
406 | printk(KERN_WARNING"Invalid parameters for " | ||
407 | "PAL call:0x%lx!\n", in0); | ||
408 | } | ||
409 | |||
410 | return result; | ||
411 | } | ||
412 | |||
295 | int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) | 413 | int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) |
296 | { | 414 | { |
297 | 415 | ||
@@ -300,14 +418,22 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
300 | int ret = 1; | 418 | int ret = 1; |
301 | 419 | ||
302 | gr28 = kvm_get_pal_call_index(vcpu); | 420 | gr28 = kvm_get_pal_call_index(vcpu); |
303 | /*printk("pal_call index:%lx\n",gr28);*/ | ||
304 | switch (gr28) { | 421 | switch (gr28) { |
305 | case PAL_CACHE_FLUSH: | 422 | case PAL_CACHE_FLUSH: |
306 | result = pal_cache_flush(vcpu); | 423 | result = pal_cache_flush(vcpu); |
307 | break; | 424 | break; |
425 | case PAL_MEM_ATTRIB: | ||
426 | result = pal_mem_attrib(vcpu); | ||
427 | break; | ||
308 | case PAL_CACHE_SUMMARY: | 428 | case PAL_CACHE_SUMMARY: |
309 | result = pal_cache_summary(vcpu); | 429 | result = pal_cache_summary(vcpu); |
310 | break; | 430 | break; |
431 | case PAL_PERF_MON_INFO: | ||
432 | result = pal_perf_mon_info(vcpu); | ||
433 | break; | ||
434 | case PAL_HALT_INFO: | ||
435 | result = pal_halt_info(vcpu); | ||
436 | break; | ||
311 | case PAL_HALT_LIGHT: | 437 | case PAL_HALT_LIGHT: |
312 | { | 438 | { |
313 | INIT_PAL_STATUS_SUCCESS(result); | 439 | INIT_PAL_STATUS_SUCCESS(result); |
@@ -317,6 +443,16 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
317 | } | 443 | } |
318 | break; | 444 | break; |
319 | 445 | ||
446 | case PAL_PREFETCH_VISIBILITY: | ||
447 | result = pal_prefetch_visibility(vcpu); | ||
448 | break; | ||
449 | case PAL_MC_DRAIN: | ||
450 | result.status = ia64_pal_mc_drain(); | ||
451 | /* FIXME: All vcpus likely call PAL_MC_DRAIN. | ||
452 | That causes the congestion. */ | ||
453 | smp_call_function(remote_pal_mc_drain, NULL, 1); | ||
454 | break; | ||
455 | |||
320 | case PAL_FREQ_RATIOS: | 456 | case PAL_FREQ_RATIOS: |
321 | result = pal_freq_ratios(vcpu); | 457 | result = pal_freq_ratios(vcpu); |
322 | break; | 458 | break; |
@@ -346,6 +482,9 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
346 | INIT_PAL_STATUS_SUCCESS(result); | 482 | INIT_PAL_STATUS_SUCCESS(result); |
347 | result.v1 = (1L << 32) | 1L; | 483 | result.v1 = (1L << 32) | 1L; |
348 | break; | 484 | break; |
485 | case PAL_REGISTER_INFO: | ||
486 | result = pal_register_info(vcpu); | ||
487 | break; | ||
349 | case PAL_VM_PAGE_SIZE: | 488 | case PAL_VM_PAGE_SIZE: |
350 | result.status = ia64_pal_vm_page_size(&result.v0, | 489 | result.status = ia64_pal_vm_page_size(&result.v0, |
351 | &result.v1); | 490 | &result.v1); |
@@ -365,12 +504,18 @@ int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
365 | result.status = ia64_pal_version( | 504 | result.status = ia64_pal_version( |
366 | (pal_version_u_t *)&result.v0, | 505 | (pal_version_u_t *)&result.v0, |
367 | (pal_version_u_t *)&result.v1); | 506 | (pal_version_u_t *)&result.v1); |
368 | |||
369 | break; | 507 | break; |
370 | case PAL_FIXED_ADDR: | 508 | case PAL_FIXED_ADDR: |
371 | result.status = PAL_STATUS_SUCCESS; | 509 | result.status = PAL_STATUS_SUCCESS; |
372 | result.v0 = vcpu->vcpu_id; | 510 | result.v0 = vcpu->vcpu_id; |
373 | break; | 511 | break; |
512 | case PAL_BRAND_INFO: | ||
513 | result = pal_get_brand_info(vcpu); | ||
514 | break; | ||
515 | case PAL_GET_PSTATE: | ||
516 | case PAL_CACHE_SHARED_INFO: | ||
517 | INIT_PAL_STATUS_UNIMPLEMENTED(result); | ||
518 | break; | ||
374 | default: | 519 | default: |
375 | INIT_PAL_STATUS_UNIMPLEMENTED(result); | 520 | INIT_PAL_STATUS_UNIMPLEMENTED(result); |
376 | printk(KERN_WARNING"kvm: Unsupported pal call," | 521 | printk(KERN_WARNING"kvm: Unsupported pal call," |
diff --git a/arch/ia64/kvm/process.c b/arch/ia64/kvm/process.c index 0e727ce0d55c..b1dc80952d91 100644 --- a/arch/ia64/kvm/process.c +++ b/arch/ia64/kvm/process.c | |||
@@ -607,7 +607,7 @@ static void set_pal_call_data(struct kvm_vcpu *vcpu) | |||
607 | p->exit_reason = EXIT_REASON_PAL_CALL; | 607 | p->exit_reason = EXIT_REASON_PAL_CALL; |
608 | } | 608 | } |
609 | 609 | ||
610 | static void set_pal_call_result(struct kvm_vcpu *vcpu) | 610 | static void get_pal_call_result(struct kvm_vcpu *vcpu) |
611 | { | 611 | { |
612 | struct exit_ctl_data *p = &vcpu->arch.exit_data; | 612 | struct exit_ctl_data *p = &vcpu->arch.exit_data; |
613 | 613 | ||
@@ -635,7 +635,7 @@ static void set_sal_call_data(struct kvm_vcpu *vcpu) | |||
635 | p->exit_reason = EXIT_REASON_SAL_CALL; | 635 | p->exit_reason = EXIT_REASON_SAL_CALL; |
636 | } | 636 | } |
637 | 637 | ||
638 | static void set_sal_call_result(struct kvm_vcpu *vcpu) | 638 | static void get_sal_call_result(struct kvm_vcpu *vcpu) |
639 | { | 639 | { |
640 | struct exit_ctl_data *p = &vcpu->arch.exit_data; | 640 | struct exit_ctl_data *p = &vcpu->arch.exit_data; |
641 | 641 | ||
@@ -658,13 +658,13 @@ void kvm_ia64_handle_break(unsigned long ifa, struct kvm_pt_regs *regs, | |||
658 | if (iim == DOMN_PAL_REQUEST) { | 658 | if (iim == DOMN_PAL_REQUEST) { |
659 | set_pal_call_data(v); | 659 | set_pal_call_data(v); |
660 | vmm_transition(v); | 660 | vmm_transition(v); |
661 | set_pal_call_result(v); | 661 | get_pal_call_result(v); |
662 | vcpu_increment_iip(v); | 662 | vcpu_increment_iip(v); |
663 | return; | 663 | return; |
664 | } else if (iim == DOMN_SAL_REQUEST) { | 664 | } else if (iim == DOMN_SAL_REQUEST) { |
665 | set_sal_call_data(v); | 665 | set_sal_call_data(v); |
666 | vmm_transition(v); | 666 | vmm_transition(v); |
667 | set_sal_call_result(v); | 667 | get_sal_call_result(v); |
668 | vcpu_increment_iip(v); | 668 | vcpu_increment_iip(v); |
669 | return; | 669 | return; |
670 | } | 670 | } |