Revision 4be21d56

b/hw/ppc/spapr.c
32 32
#include "sysemu/cpus.h"
33 33
#include "sysemu/kvm.h"
34 34
#include "kvm_ppc.h"
35
#include "mmu-hash64.h"
35 36

  
36 37
#include "hw/boards.h"
37 38
#include "hw/ppc/ppc.h"
......
666 667

  
667 668
    env->spr[SPR_HIOR] = 0;
668 669

  
669
    env->external_htab = spapr->htab;
670
    env->external_htab = (uint8_t *)spapr->htab;
670 671
    env->htab_base = -1;
671 672
    env->htab_mask = HTAB_SIZE(spapr) - 1;
672 673
    env->spr[SPR_SDR1] = (target_ulong)(uintptr_t)spapr->htab |
......
710 711
    }
711 712
}
712 713

  
714
static const VMStateDescription vmstate_spapr = {
715
    .name = "spapr",
716
    .version_id = 1,
717
    .minimum_version_id = 1,
718
    .minimum_version_id_old = 1,
719
    .fields      = (VMStateField []) {
720
        VMSTATE_UINT32(next_irq, sPAPREnvironment),
721

  
722
        /* RTC offset */
723
        VMSTATE_UINT64(rtc_offset, sPAPREnvironment),
724

  
725
        VMSTATE_END_OF_LIST()
726
    },
727
};
728

  
729
#define HPTE(_table, _i)   (void *)(((uint64_t *)(_table)) + ((_i) * 2))
730
#define HPTE_VALID(_hpte)  (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID)
731
#define HPTE_DIRTY(_hpte)  (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY)
732
#define CLEAN_HPTE(_hpte)  ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY))
733

  
734
static int htab_save_setup(QEMUFile *f, void *opaque)
735
{
736
    sPAPREnvironment *spapr = opaque;
737

  
738
    spapr->htab_save_index = 0;
739
    spapr->htab_first_pass = true;
740

  
741
    /* "Iteration" header */
742
    qemu_put_be32(f, spapr->htab_shift);
743

  
744
    return 0;
745
}
746

  
747
#define MAX_ITERATION_NS    5000000 /* 5 ms */
748

  
749
static void htab_save_first_pass(QEMUFile *f, sPAPREnvironment *spapr,
750
                                 int64_t max_ns)
751
{
752
    int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64;
753
    int index = spapr->htab_save_index;
754
    int64_t starttime = qemu_get_clock_ns(rt_clock);
755

  
756
    assert(spapr->htab_first_pass);
757

  
758
    do {
759
        int chunkstart;
760

  
761
        /* Consume invalid HPTEs */
762
        while ((index < htabslots)
763
               && !HPTE_VALID(HPTE(spapr->htab, index))) {
764
            index++;
765
            CLEAN_HPTE(HPTE(spapr->htab, index));
766
        }
767

  
768
        /* Consume valid HPTEs */
769
        chunkstart = index;
770
        while ((index < htabslots)
771
               && HPTE_VALID(HPTE(spapr->htab, index))) {
772
            index++;
773
            CLEAN_HPTE(HPTE(spapr->htab, index));
774
        }
775

  
776
        if (index > chunkstart) {
777
            int n_valid = index - chunkstart;
778

  
779
            qemu_put_be32(f, chunkstart);
780
            qemu_put_be16(f, n_valid);
781
            qemu_put_be16(f, 0);
782
            qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
783
                            HASH_PTE_SIZE_64 * n_valid);
784

  
785
            if ((qemu_get_clock_ns(rt_clock) - starttime) > max_ns) {
786
                break;
787
            }
788
        }
789
    } while ((index < htabslots) && !qemu_file_rate_limit(f));
790

  
791
    if (index >= htabslots) {
792
        assert(index == htabslots);
793
        index = 0;
794
        spapr->htab_first_pass = false;
795
    }
796
    spapr->htab_save_index = index;
797
}
798

  
799
static bool htab_save_later_pass(QEMUFile *f, sPAPREnvironment *spapr,
800
                                 int64_t max_ns)
801
{
802
    bool final = max_ns < 0;
803
    int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64;
804
    int examined = 0, sent = 0;
805
    int index = spapr->htab_save_index;
806
    int64_t starttime = qemu_get_clock_ns(rt_clock);
807

  
808
    assert(!spapr->htab_first_pass);
809

  
810
    do {
811
        int chunkstart, invalidstart;
812

  
813
        /* Consume non-dirty HPTEs */
814
        while ((index < htabslots)
815
               && !HPTE_DIRTY(HPTE(spapr->htab, index))) {
816
            index++;
817
            examined++;
818
        }
819

  
820
        chunkstart = index;
821
        /* Consume valid dirty HPTEs */
822
        while ((index < htabslots)
823
               && HPTE_DIRTY(HPTE(spapr->htab, index))
824
               && HPTE_VALID(HPTE(spapr->htab, index))) {
825
            CLEAN_HPTE(HPTE(spapr->htab, index));
826
            index++;
827
            examined++;
828
        }
829

  
830
        invalidstart = index;
831
        /* Consume invalid dirty HPTEs */
832
        while ((index < htabslots)
833
               && HPTE_DIRTY(HPTE(spapr->htab, index))
834
               && !HPTE_VALID(HPTE(spapr->htab, index))) {
835
            CLEAN_HPTE(HPTE(spapr->htab, index));
836
            index++;
837
            examined++;
838
        }
839

  
840
        if (index > chunkstart) {
841
            int n_valid = invalidstart - chunkstart;
842
            int n_invalid = index - invalidstart;
843

  
844
            qemu_put_be32(f, chunkstart);
845
            qemu_put_be16(f, n_valid);
846
            qemu_put_be16(f, n_invalid);
847
            qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
848
                            HASH_PTE_SIZE_64 * n_valid);
849
            sent += index - chunkstart;
850

  
851
            if (!final && (qemu_get_clock_ns(rt_clock) - starttime) > max_ns) {
852
                break;
853
            }
854
        }
855

  
856
        if (examined >= htabslots) {
857
            break;
858
        }
859

  
860
        if (index >= htabslots) {
861
            assert(index == htabslots);
862
            index = 0;
863
        }
864
    } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final));
865

  
866
    if (index >= htabslots) {
867
        assert(index == htabslots);
868
        index = 0;
869
    }
870

  
871
    spapr->htab_save_index = index;
872

  
873
    return (examined >= htabslots) && (sent == 0);
874
}
875

  
876
static int htab_save_iterate(QEMUFile *f, void *opaque)
877
{
878
    sPAPREnvironment *spapr = opaque;
879
    bool nothingleft = false;;
880

  
881
    /* Iteration header */
882
    qemu_put_be32(f, 0);
883

  
884
    if (spapr->htab_first_pass) {
885
        htab_save_first_pass(f, spapr, MAX_ITERATION_NS);
886
    } else {
887
        nothingleft = htab_save_later_pass(f, spapr, MAX_ITERATION_NS);
888
    }
889

  
890
    /* End marker */
891
    qemu_put_be32(f, 0);
892
    qemu_put_be16(f, 0);
893
    qemu_put_be16(f, 0);
894

  
895
    return nothingleft ? 1 : 0;
896
}
897

  
898
static int htab_save_complete(QEMUFile *f, void *opaque)
899
{
900
    sPAPREnvironment *spapr = opaque;
901

  
902
    /* Iteration header */
903
    qemu_put_be32(f, 0);
904

  
905
    htab_save_later_pass(f, spapr, -1);
906

  
907
    /* End marker */
908
    qemu_put_be32(f, 0);
909
    qemu_put_be16(f, 0);
910
    qemu_put_be16(f, 0);
911

  
912
    return 0;
913
}
914

  
915
static int htab_load(QEMUFile *f, void *opaque, int version_id)
916
{
917
    sPAPREnvironment *spapr = opaque;
918
    uint32_t section_hdr;
919

  
920
    if (version_id < 1 || version_id > 1) {
921
        fprintf(stderr, "htab_load() bad version\n");
922
        return -EINVAL;
923
    }
924

  
925
    section_hdr = qemu_get_be32(f);
926

  
927
    if (section_hdr) {
928
        /* First section, just the hash shift */
929
        if (spapr->htab_shift != section_hdr) {
930
            return -EINVAL;
931
        }
932
        return 0;
933
    }
934

  
935
    while (true) {
936
        uint32_t index;
937
        uint16_t n_valid, n_invalid;
938

  
939
        index = qemu_get_be32(f);
940
        n_valid = qemu_get_be16(f);
941
        n_invalid = qemu_get_be16(f);
942

  
943
        if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) {
944
            /* End of Stream */
945
            break;
946
        }
947

  
948
        if ((index + n_valid + n_invalid) >=
949
            (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) {
950
            /* Bad index in stream */
951
            fprintf(stderr, "htab_load() bad index %d (%hd+%hd entries) "
952
                    "in htab stream\n", index, n_valid, n_invalid);
953
            return -EINVAL;
954
        }
955

  
956
        if (n_valid) {
957
            qemu_get_buffer(f, HPTE(spapr->htab, index),
958
                            HASH_PTE_SIZE_64 * n_valid);
959
        }
960
        if (n_invalid) {
961
            memset(HPTE(spapr->htab, index + n_valid), 0,
962
                   HASH_PTE_SIZE_64 * n_invalid);
963
        }
964
    }
965

  
966
    return 0;
967
}
968

  
969
static SaveVMHandlers savevm_htab_handlers = {
970
    .save_live_setup = htab_save_setup,
971
    .save_live_iterate = htab_save_iterate,
972
    .save_live_complete = htab_save_complete,
973
    .load_state = htab_load,
974
};
975

  
713 976
/* pSeries LPAR / sPAPR hardware init */
714 977
static void ppc_spapr_init(QEMUMachineInitArgs *args)
715 978
{
......
950 1213

  
951 1214
    spapr->entry_point = 0x100;
952 1215

  
1216
    vmstate_register(NULL, 0, &vmstate_spapr, spapr);
1217
    register_savevm_live(NULL, "spapr/htab", -1, 1,
1218
                         &savevm_htab_handlers, spapr);
1219

  
953 1220
    /* Prepare the device tree */
954 1221
    spapr->fdt_skel = spapr_create_fdt_skel(cpu_model,
955 1222
                                            initrd_base, initrd_size,
b/hw/ppc/spapr_hcall.c
115 115
    }
116 116
    ppc_hash64_store_hpte1(env, hpte, ptel);
117 117
    /* eieio();  FIXME: need some sort of barrier for smp? */
118
    ppc_hash64_store_hpte0(env, hpte, pteh);
118
    ppc_hash64_store_hpte0(env, hpte, pteh | HPTE64_V_HPTE_DIRTY);
119 119

  
120 120
    args[0] = pte_index + i;
121 121
    return H_SUCCESS;
......
152 152
    }
153 153
    *vp = v;
154 154
    *rp = r;
155
    ppc_hash64_store_hpte0(env, hpte, 0);
155
    ppc_hash64_store_hpte0(env, hpte, HPTE64_V_HPTE_DIRTY);
156 156
    rb = compute_tlbie_rb(v, r, ptex);
157 157
    ppc_tlb_invalidate_one(env, rb);
158 158
    return REMOVE_SUCCESS;
......
282 282
    r |= (flags << 48) & HPTE64_R_KEY_HI;
283 283
    r |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO);
284 284
    rb = compute_tlbie_rb(v, r, pte_index);
285
    ppc_hash64_store_hpte0(env, hpte, v & ~HPTE64_V_VALID);
285
    ppc_hash64_store_hpte0(env, hpte, (v & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY);
286 286
    ppc_tlb_invalidate_one(env, rb);
287 287
    ppc_hash64_store_hpte1(env, hpte, r);
288 288
    /* Don't need a memory barrier, due to qemu's global lock */
289
    ppc_hash64_store_hpte0(env, hpte, v);
289
    ppc_hash64_store_hpte0(env, hpte, v | HPTE64_V_HPTE_DIRTY);
290 290
    return H_SUCCESS;
291 291
}
292 292

  
b/include/hw/ppc/spapr.h
9 9
struct sPAPRNVRAM;
10 10
struct icp_state;
11 11

  
12
#define HPTE64_V_HPTE_DIRTY     0x0000000000000040ULL
13

  
12 14
typedef struct sPAPREnvironment {
13 15
    struct VIOsPAPRBus *vio_bus;
14 16
    QLIST_HEAD(, sPAPRPHBState) phbs;
......
17 19

  
18 20
    hwaddr ram_limit;
19 21
    void *htab;
20
    long htab_shift;
22
    uint32_t htab_shift;
21 23
    hwaddr rma_size;
22 24
    int vrma_adjust;
23 25
    hwaddr fdt_addr, rtas_addr;
24 26
    long rtas_size;
25 27
    void *fdt_skel;
26 28
    target_ulong entry_point;
27
    int next_irq;
28
    int rtc_offset;
29
    uint32_t next_irq;
30
    uint64_t rtc_offset;
29 31
    char *cpu_model;
30 32
    bool has_graphics;
31 33

  
32 34
    uint32_t epow_irq;
33 35
    Notifier epow_notifier;
36

  
37
    /* Migration state */
38
    int htab_save_index;
39
    bool htab_first_pass;
34 40
} sPAPREnvironment;
35 41

  
36 42
#define H_SUCCESS         0

Also available in: Unified diff