aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64
diff options
context:
space:
mode:
authorXiantao Zhang <xiantao.zhang@intel.com>2009-01-20 22:21:27 -0500
committerAvi Kivity <avi@redhat.com>2009-03-24 05:03:06 -0400
commit7d656bd996b68737d5d07643bc57311059038d67 (patch)
tree674c9d3910547c1185785a7c827e54e2425f9fd8 /arch/ia64
parent4b7bb626e3133eab131328a0770864b322c1bfe6 (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')
-rw-r--r--arch/ia64/kvm/kvm_fw.c151
-rw-r--r--arch/ia64/kvm/process.c8
2 files changed, 152 insertions, 7 deletions
diff --git a/arch/ia64/kvm/kvm_fw.c b/arch/ia64/kvm/kvm_fw.c
index cb7600bdff9..a8ae52ed563 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
230static 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
230static struct ia64_pal_retval pal_cache_info(struct kvm_vcpu *vcpu) 242static 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)
268static struct ia64_pal_retval pal_vm_info(struct kvm_vcpu *vcpu) 280static 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
311static 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
334static 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
354static 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
364static void remote_pal_prefetch_visibility(void *v)
365{
366 s64 trans_type = (s64)v;
367 ia64_pal_prefetch_visibility(trans_type);
368}
369
370static 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
387static void remote_pal_mc_drain(void *v)
388{
389 ia64_pal_mc_drain();
390}
391
392static 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
295int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *run) 413int 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 0e727ce0d55..b1dc80952d9 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
610static void set_pal_call_result(struct kvm_vcpu *vcpu) 610static 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
638static void set_sal_call_result(struct kvm_vcpu *vcpu) 638static 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 }