Revision 46dbef6a

b/kvm-all.c
402 402
    return ret;
403 403
}
404 404

  
405
void kvm_set_phys_mem(target_phys_addr_t start_addr,
406
		       ram_addr_t size,
407
		       ram_addr_t phys_offset)
408
{
409
    KVMState *s = kvm_state;
410
    ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
411
    KVMSlot *mem, old;
412
    int err;
413

  
414
    if (start_addr & ~TARGET_PAGE_MASK) {
415
        if (flags >= IO_MEM_UNASSIGNED) {
416
            if (!kvm_lookup_overlapping_slot(s, start_addr,
417
                                             start_addr + size)) {
418
                return;
419
            }
420
            fprintf(stderr, "Unaligned split of a KVM memory slot\n");
421
        } else {
422
            fprintf(stderr, "Only page-aligned memory slots supported\n");
423
        }
424
        abort();
425
    }
426

  
427
    /* KVM does not support read-only slots */
428
    phys_offset &= ~IO_MEM_ROM;
429

  
430
    while (1) {
431
        mem = kvm_lookup_overlapping_slot(s, start_addr, start_addr + size);
432
        if (!mem) {
433
            break;
434
        }
435

  
436
        if (flags < IO_MEM_UNASSIGNED && start_addr >= mem->start_addr &&
437
            (start_addr + size <= mem->start_addr + mem->memory_size) &&
438
            (phys_offset - start_addr == mem->phys_offset - mem->start_addr)) {
439
            /* The new slot fits into the existing one and comes with
440
             * identical parameters - nothing to be done. */
441
            return;
442
        }
443

  
444
        old = *mem;
445

  
446
        /* unregister the overlapping slot */
447
        mem->memory_size = 0;
448
        err = kvm_set_user_memory_region(s, mem);
449
        if (err) {
450
            fprintf(stderr, "%s: error unregistering overlapping slot: %s\n",
451
                    __func__, strerror(-err));
452
            abort();
453
        }
454

  
455
        /* Workaround for older KVM versions: we can't join slots, even not by
456
         * unregistering the previous ones and then registering the larger
457
         * slot. We have to maintain the existing fragmentation. Sigh.
458
         *
459
         * This workaround assumes that the new slot starts at the same
460
         * address as the first existing one. If not or if some overlapping
461
         * slot comes around later, we will fail (not seen in practice so far)
462
         * - and actually require a recent KVM version. */
463
        if (s->broken_set_mem_region &&
464
            old.start_addr == start_addr && old.memory_size < size &&
465
            flags < IO_MEM_UNASSIGNED) {
466
            mem = kvm_alloc_slot(s);
467
            mem->memory_size = old.memory_size;
468
            mem->start_addr = old.start_addr;
469
            mem->phys_offset = old.phys_offset;
470
            mem->flags = 0;
471

  
472
            err = kvm_set_user_memory_region(s, mem);
473
            if (err) {
474
                fprintf(stderr, "%s: error updating slot: %s\n", __func__,
475
                        strerror(-err));
476
                abort();
477
            }
478

  
479
            start_addr += old.memory_size;
480
            phys_offset += old.memory_size;
481
            size -= old.memory_size;
482
            continue;
483
        }
484

  
485
        /* register prefix slot */
486
        if (old.start_addr < start_addr) {
487
            mem = kvm_alloc_slot(s);
488
            mem->memory_size = start_addr - old.start_addr;
489
            mem->start_addr = old.start_addr;
490
            mem->phys_offset = old.phys_offset;
491
            mem->flags = 0;
492

  
493
            err = kvm_set_user_memory_region(s, mem);
494
            if (err) {
495
                fprintf(stderr, "%s: error registering prefix slot: %s\n",
496
                        __func__, strerror(-err));
497
                abort();
498
            }
499
        }
500

  
501
        /* register suffix slot */
502
        if (old.start_addr + old.memory_size > start_addr + size) {
503
            ram_addr_t size_delta;
504

  
505
            mem = kvm_alloc_slot(s);
506
            mem->start_addr = start_addr + size;
507
            size_delta = mem->start_addr - old.start_addr;
508
            mem->memory_size = old.memory_size - size_delta;
509
            mem->phys_offset = old.phys_offset + size_delta;
510
            mem->flags = 0;
511

  
512
            err = kvm_set_user_memory_region(s, mem);
513
            if (err) {
514
                fprintf(stderr, "%s: error registering suffix slot: %s\n",
515
                        __func__, strerror(-err));
516
                abort();
517
            }
518
        }
519
    }
520

  
521
    /* in case the KVM bug workaround already "consumed" the new slot */
522
    if (!size)
523
        return;
524

  
525
    /* KVM does not need to know about this memory */
526
    if (flags >= IO_MEM_UNASSIGNED)
527
        return;
528

  
529
    mem = kvm_alloc_slot(s);
530
    mem->memory_size = size;
531
    mem->start_addr = start_addr;
532
    mem->phys_offset = phys_offset;
533
    mem->flags = 0;
534

  
535
    err = kvm_set_user_memory_region(s, mem);
536
    if (err) {
537
        fprintf(stderr, "%s: error registering slot: %s\n", __func__,
538
                strerror(-err));
539
        abort();
540
    }
541
}
542

  
405 543
int kvm_init(int smp_cpus)
406 544
{
407 545
    static const char upgrade_note[] =
......
680 818
    return ret;
681 819
}
682 820

  
683
void kvm_set_phys_mem(target_phys_addr_t start_addr,
684
                      ram_addr_t size,
685
                      ram_addr_t phys_offset)
686
{
687
    KVMState *s = kvm_state;
688
    ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
689
    KVMSlot *mem, old;
690
    int err;
691

  
692
    if (start_addr & ~TARGET_PAGE_MASK) {
693
        if (flags >= IO_MEM_UNASSIGNED) {
694
            if (!kvm_lookup_overlapping_slot(s, start_addr,
695
                                             start_addr + size)) {
696
                return;
697
            }
698
            fprintf(stderr, "Unaligned split of a KVM memory slot\n");
699
        } else {
700
            fprintf(stderr, "Only page-aligned memory slots supported\n");
701
        }
702
        abort();
703
    }
704

  
705
    /* KVM does not support read-only slots */
706
    phys_offset &= ~IO_MEM_ROM;
707

  
708
    while (1) {
709
        mem = kvm_lookup_overlapping_slot(s, start_addr, start_addr + size);
710
        if (!mem) {
711
            break;
712
        }
713

  
714
        if (flags < IO_MEM_UNASSIGNED && start_addr >= mem->start_addr &&
715
            (start_addr + size <= mem->start_addr + mem->memory_size) &&
716
            (phys_offset - start_addr == mem->phys_offset - mem->start_addr)) {
717
            /* The new slot fits into the existing one and comes with
718
             * identical parameters - nothing to be done. */
719
            return;
720
        }
721

  
722
        old = *mem;
723

  
724
        /* unregister the overlapping slot */
725
        mem->memory_size = 0;
726
        err = kvm_set_user_memory_region(s, mem);
727
        if (err) {
728
            fprintf(stderr, "%s: error unregistering overlapping slot: %s\n",
729
                    __func__, strerror(-err));
730
            abort();
731
        }
732

  
733
        /* Workaround for older KVM versions: we can't join slots, even not by
734
         * unregistering the previous ones and then registering the larger
735
         * slot. We have to maintain the existing fragmentation. Sigh.
736
         *
737
         * This workaround assumes that the new slot starts at the same
738
         * address as the first existing one. If not or if some overlapping
739
         * slot comes around later, we will fail (not seen in practice so far)
740
         * - and actually require a recent KVM version. */
741
        if (s->broken_set_mem_region &&
742
            old.start_addr == start_addr && old.memory_size < size &&
743
            flags < IO_MEM_UNASSIGNED) {
744
            mem = kvm_alloc_slot(s);
745
            mem->memory_size = old.memory_size;
746
            mem->start_addr = old.start_addr;
747
            mem->phys_offset = old.phys_offset;
748
            mem->flags = 0;
749

  
750
            err = kvm_set_user_memory_region(s, mem);
751
            if (err) {
752
                fprintf(stderr, "%s: error updating slot: %s\n", __func__,
753
                        strerror(-err));
754
                abort();
755
            }
756

  
757
            start_addr += old.memory_size;
758
            phys_offset += old.memory_size;
759
            size -= old.memory_size;
760
            continue;
761
        }
762

  
763
        /* register prefix slot */
764
        if (old.start_addr < start_addr) {
765
            mem = kvm_alloc_slot(s);
766
            mem->memory_size = start_addr - old.start_addr;
767
            mem->start_addr = old.start_addr;
768
            mem->phys_offset = old.phys_offset;
769
            mem->flags = 0;
770

  
771
            err = kvm_set_user_memory_region(s, mem);
772
            if (err) {
773
                fprintf(stderr, "%s: error registering prefix slot: %s\n",
774
                        __func__, strerror(-err));
775
                abort();
776
            }
777
        }
778

  
779
        /* register suffix slot */
780
        if (old.start_addr + old.memory_size > start_addr + size) {
781
            ram_addr_t size_delta;
782

  
783
            mem = kvm_alloc_slot(s);
784
            mem->start_addr = start_addr + size;
785
            size_delta = mem->start_addr - old.start_addr;
786
            mem->memory_size = old.memory_size - size_delta;
787
            mem->phys_offset = old.phys_offset + size_delta;
788
            mem->flags = 0;
789

  
790
            err = kvm_set_user_memory_region(s, mem);
791
            if (err) {
792
                fprintf(stderr, "%s: error registering suffix slot: %s\n",
793
                        __func__, strerror(-err));
794
                abort();
795
            }
796
        }
797
    }
798

  
799
    /* in case the KVM bug workaround already "consumed" the new slot */
800
    if (!size)
801
        return;
802

  
803
    /* KVM does not need to know about this memory */
804
    if (flags >= IO_MEM_UNASSIGNED)
805
        return;
806

  
807
    mem = kvm_alloc_slot(s);
808
    mem->memory_size = size;
809
    mem->start_addr = start_addr;
810
    mem->phys_offset = phys_offset;
811
    mem->flags = 0;
812

  
813
    err = kvm_set_user_memory_region(s, mem);
814
    if (err) {
815
        fprintf(stderr, "%s: error registering slot: %s\n", __func__,
816
                strerror(-err));
817
        abort();
818
    }
819
}
820

  
821 821
int kvm_ioctl(KVMState *s, int type, ...)
822 822
{
823 823
    int ret;

Also available in: Unified diff