~ubuntu-branches/ubuntu/vivid/qemu/vivid

« back to all changes in this revision

Viewing changes to linux-user/main.c

  • Committer: Package Import Robot
  • Author(s): dann frazier
  • Date: 2014-02-11 15:41:53 UTC
  • Revision ID: package-import@ubuntu.com-20140211154153-2d001tf0ium08u81
Tags: 1.7.0+dfsg-3ubuntu2
* Backport changes to enable qemu-user-static support for aarch64
* debian/control: add ppc64el to Architectures
* debian/rules: only install qemu-system-aarch64 on arm64.
  Fixes a FTBFS  when built twice in a row on non-arm64 due to a stale
  debian/qemu-system-aarch64 directory

Show diffs side-by-side

added added

removed removed

Lines of Context:
69
69
static void usage(void);
70
70
 
71
71
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
72
 
const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
 
72
 
 
73
#ifdef TARGET_AARCH64
 
74
# define UNAME_RELEASE "3.7.0"
 
75
#else
 
76
# define UNAME_RELEASE CONFIG_UNAME_RELEASE
 
77
#endif
 
78
 
 
79
const char *qemu_uname_release = UNAME_RELEASE;
73
80
 
74
81
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
75
82
   we allocate a bigger stack. Need a better solution, for example
566
573
        end_exclusive();
567
574
        break;
568
575
    case 0xffff0fe0: /* __kernel_get_tls */
569
 
        env->regs[0] = env->cp15.c13_tls2;
 
576
        env->regs[0] = env->cp15.tpidrro_el0;
570
577
        break;
571
578
    case 0xffff0f60: /* __kernel_cmpxchg64 */
572
579
        arm_kernel_cmpxchg64_helper(env);
585
592
 
586
593
    return 0;
587
594
}
588
 
#endif
589
595
 
 
596
/* Store exclusive handling for AArch32 */
590
597
static int do_strex(CPUARMState *env)
591
598
{
592
 
    uint32_t val;
 
599
    uint64_t val;
593
600
    int size;
594
601
    int rc = 1;
595
602
    int segv = 0;
596
603
    uint32_t addr;
597
604
    start_exclusive();
598
 
    addr = env->exclusive_addr;
599
 
    if (addr != env->exclusive_test) {
 
605
    if (env->exclusive_addr != env->exclusive_test) {
600
606
        goto fail;
601
607
    }
 
608
    /* We know we're always AArch32 so the address is in uint32_t range
 
609
     * unless it was the -1 exclusive-monitor-lost value (which won't
 
610
     * match exclusive_test above).
 
611
     */
 
612
    assert(extract64(env->exclusive_addr, 32, 32) == 0);
 
613
    addr = env->exclusive_addr;
602
614
    size = env->exclusive_info & 0xf;
603
615
    switch (size) {
604
616
    case 0:
618
630
        env->cp15.c6_data = addr;
619
631
        goto done;
620
632
    }
621
 
    if (val != env->exclusive_val) {
622
 
        goto fail;
623
 
    }
624
633
    if (size == 3) {
625
 
        segv = get_user_u32(val, addr + 4);
 
634
        uint32_t valhi;
 
635
        segv = get_user_u32(valhi, addr + 4);
626
636
        if (segv) {
627
637
            env->cp15.c6_data = addr + 4;
628
638
            goto done;
629
639
        }
630
 
        if (val != env->exclusive_high) {
631
 
            goto fail;
632
 
        }
633
 
    }
 
640
        val = deposit64(val, 32, 32, valhi);
 
641
    }
 
642
    if (val != env->exclusive_val) {
 
643
        goto fail;
 
644
    }
 
645
 
634
646
    val = env->regs[(env->exclusive_info >> 8) & 0xf];
635
647
    switch (size) {
636
648
    case 0:
665
677
    return segv;
666
678
}
667
679
 
668
 
#ifdef TARGET_ABI32
669
680
void cpu_loop(CPUARMState *env)
670
681
{
671
682
    CPUState *cs = CPU(arm_env_get_cpu(env));
880
891
 
881
892
#else
882
893
 
 
894
/*
 
895
 * Handle AArch64 store-release exclusive
 
896
 *
 
897
 * rs = gets the status result of store exclusive
 
898
 * rt = is the register that is stored
 
899
 * rt2 = is the second register store (in STP)
 
900
 *
 
901
 */
 
902
static int do_strex_a64(CPUARMState *env)
 
903
{
 
904
    uint64_t val;
 
905
    int size;
 
906
    bool is_pair;
 
907
    int rc = 1;
 
908
    int segv = 0;
 
909
    uint64_t addr;
 
910
    int rs, rt, rt2;
 
911
 
 
912
    start_exclusive();
 
913
    /* size | is_pair << 2 | (rs << 4) | (rt << 9) | (rt2 << 14)); */
 
914
    size = extract32(env->exclusive_info, 0, 2);
 
915
    is_pair = extract32(env->exclusive_info, 2, 1);
 
916
    rs = extract32(env->exclusive_info, 4, 5);
 
917
    rt = extract32(env->exclusive_info, 9, 5);
 
918
    rt2 = extract32(env->exclusive_info, 14, 5);
 
919
 
 
920
    addr = env->exclusive_addr;
 
921
 
 
922
    if (addr != env->exclusive_test) {
 
923
        goto finish;
 
924
    }
 
925
 
 
926
    switch (size) {
 
927
    case 0:
 
928
        segv = get_user_u8(val, addr);
 
929
        break;
 
930
    case 1:
 
931
        segv = get_user_u16(val, addr);
 
932
        break;
 
933
    case 2:
 
934
        segv = get_user_u32(val, addr);
 
935
        break;
 
936
    case 3:
 
937
        segv = get_user_u64(val, addr);
 
938
        break;
 
939
    default:
 
940
        abort();
 
941
    }
 
942
    if (segv) {
 
943
        env->cp15.c6_data = addr;
 
944
        goto error;
 
945
    }
 
946
    if (val != env->exclusive_val) {
 
947
        goto finish;
 
948
    }
 
949
    if (is_pair) {
 
950
        if (size == 2) {
 
951
            segv = get_user_u32(val, addr + 4);
 
952
        } else {
 
953
            segv = get_user_u64(val, addr + 8);
 
954
        }
 
955
        if (segv) {
 
956
            env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
 
957
            goto error;
 
958
        }
 
959
        if (val != env->exclusive_high) {
 
960
            goto finish;
 
961
        }
 
962
    }
 
963
    val = env->xregs[rt];
 
964
    switch (size) {
 
965
    case 0:
 
966
        segv = put_user_u8(val, addr);
 
967
        break;
 
968
    case 1:
 
969
        segv = put_user_u16(val, addr);
 
970
        break;
 
971
    case 2:
 
972
        segv = put_user_u32(val, addr);
 
973
        break;
 
974
    case 3:
 
975
        segv = put_user_u64(val, addr);
 
976
        break;
 
977
    }
 
978
    if (segv) {
 
979
        goto error;
 
980
    }
 
981
    if (is_pair) {
 
982
        val = env->xregs[rt2];
 
983
        if (size == 2) {
 
984
            segv = put_user_u32(val, addr + 4);
 
985
        } else {
 
986
            segv = put_user_u64(val, addr + 8);
 
987
        }
 
988
        if (segv) {
 
989
            env->cp15.c6_data = addr + (size == 2 ? 4 : 8);
 
990
            goto error;
 
991
        }
 
992
    }
 
993
    rc = 0;
 
994
finish:
 
995
    env->pc += 4;
 
996
    /* rs == 31 encodes a write to the ZR, thus throwing away
 
997
     * the status return. This is rather silly but valid.
 
998
     */
 
999
    if (rs < 31) {
 
1000
        env->xregs[rs] = rc;
 
1001
    }
 
1002
error:
 
1003
    /* instruction faulted, PC does not advance */
 
1004
    /* either way a strex releases any exclusive lock we have */
 
1005
    env->exclusive_addr = -1;
 
1006
    end_exclusive();
 
1007
    return segv;
 
1008
}
 
1009
 
883
1010
/* AArch64 main loop */
884
1011
void cpu_loop(CPUARMState *env)
885
1012
{
939
1066
            }
940
1067
            break;
941
1068
        case EXCP_STREX:
942
 
            if (do_strex(env)) {
 
1069
            if (do_strex_a64(env)) {
943
1070
                addr = env->cp15.c6_data;
944
1071
                goto do_segv;
945
1072
            }
951
1078
            abort();
952
1079
        }
953
1080
        process_pending_signals(env);
 
1081
        /* Exception return on AArch64 always clears the exclusive monitor,
 
1082
         * so any return to running guest code implies this.
 
1083
         * A strex (successful or otherwise) also clears the monitor, so
 
1084
         * we don't need to specialcase EXCP_STREX.
 
1085
         */
 
1086
        env->exclusive_addr = -1;
954
1087
    }
955
1088
}
956
1089
#endif /* ndef TARGET_ABI32 */