libshit

Just some random shit
git clone https://git.neptards.moe/neptards/libshit.git
Log | Files | Refs | Submodules | README | LICENSE

qemu-8.1.3.patch (13110B)


      1 diff --git a/linux-user/main.c b/linux-user/main.c
      2 index 96be354897..bc4c8864c7 100644
      3 --- a/linux-user/main.c
      4 +++ b/linux-user/main.c
      5 @@ -124,6 +124,7 @@ static void usage(int exitcode);
      6  
      7  static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
      8  const char *qemu_uname_release;
      9 +const char *qemu_execve_path;
     10  
     11  #if !defined(TARGET_DEFAULT_STACK_SIZE)
     12  /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
     13 @@ -370,6 +371,11 @@ static void handle_arg_guest_base(const char *arg)
     14      have_guest_base = true;
     15  }
     16  
     17 +static void handle_arg_execve(const char *arg)
     18 +{
     19 +    qemu_execve_path = strdup(arg);
     20 +}
     21 +
     22  static void handle_arg_reserved_va(const char *arg)
     23  {
     24      char *p;
     25 @@ -486,6 +492,8 @@ static const struct qemu_argument arg_table[] = {
     26       "uname",      "set qemu uname release string to 'uname'"},
     27      {"B",          "QEMU_GUEST_BASE",  true,  handle_arg_guest_base,
     28       "address",    "set guest_base address to 'address'"},
     29 +    {"execve",     "QEMU_EXECVE",      true,  handle_arg_execve,
     30 +     "",           "use this interpreter when a process calls execve()"},
     31      {"R",          "QEMU_RESERVED_VA", true,  handle_arg_reserved_va,
     32       "size",       "reserve 'size' bytes for guest virtual address space"},
     33      {"d",          "QEMU_LOG",         true,  handle_arg_log,
     34 diff --git a/linux-user/syscall.c b/linux-user/syscall.c
     35 index 9353268cc1..790744adfb 100644
     36 --- a/linux-user/syscall.c
     37 +++ b/linux-user/syscall.c
     38 @@ -125,6 +125,7 @@
     39  #include <libdrm/drm.h>
     40  #include <libdrm/i915_drm.h>
     41  #endif
     42 +#include <linux/binfmts.h>
     43  #include "linux_loop.h"
     44  #include "uname.h"
     45  
     46 @@ -8680,6 +8681,137 @@ ssize_t do_guest_readlink(const char *pathname, char *buf, size_t bufsiz)
     47      return ret;
     48  }
     49  
     50 +/* qemu_execve() Must return target values and target errnos.
     51 + *
     52 + * Although execve() is not an interruptible syscall it is
     53 + * a special case where we must use the safe_syscall wrapper:
     54 + * if we allow a signal to happen before we make the host
     55 + * syscall then we will 'lose' it, because at the point of
     56 + * execve the process leaves QEMU's control. So we use the
     57 + * safe syscall wrapper to ensure that we either take the
     58 + * signal as a guest signal, or else it does not happen
     59 + * before the execve completes and makes it the other
     60 + * program's problem.
     61 + */
     62 +static abi_long qemu_execve(int dirfd, char *filename, char *argv[],
     63 +                            char *envp[], int flags, bool is_execveat)
     64 +{
     65 +    char *i_arg = NULL, *i_name = NULL;
     66 +    char **new_argp;
     67 +    int argc, fd, ret, i, offset = 5;
     68 +    char *cp;
     69 +    char buf[BINPRM_BUF_SIZE];
     70 +
     71 +    /* normal execve case */
     72 +    if (qemu_execve_path == NULL || *qemu_execve_path == 0) {
     73 +        return get_errno(is_execveat ?
     74 +                         safe_execveat(dirfd, filename, argv, envp, flags) :
     75 +                         safe_execve(filename, argv, envp));
     76 +    }
     77 +
     78 +    if (is_execveat) {
     79 +        return -TARGET_ENOSYS;
     80 +    }
     81 +
     82 +    for (argc = 0; argv[argc] != NULL; argc++) {
     83 +        /* nothing */ ;
     84 +    }
     85 +
     86 +    fd = open(filename, O_RDONLY);
     87 +    if (fd == -1) {
     88 +        return get_errno(fd);
     89 +    }
     90 +
     91 +    ret = read(fd, buf, BINPRM_BUF_SIZE);
     92 +    if (ret == -1) {
     93 +        close(fd);
     94 +        return get_errno(ret);
     95 +    }
     96 +
     97 +    /* if we have less than 2 bytes, we can guess it is not executable */
     98 +    if (ret < 2) {
     99 +        close(fd);
    100 +        return -host_to_target_errno(ENOEXEC);
    101 +    }
    102 +
    103 +    close(fd);
    104 +
    105 +    /* adapted from the kernel
    106 +     * https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/binfmt_script.c
    107 +     */
    108 +    if ((buf[0] == '#') && (buf[1] == '!')) {
    109 +        /*
    110 +         * This section does the #! interpretation.
    111 +         * Sorta complicated, but hopefully it will work.  -TYT
    112 +         */
    113 +
    114 +        buf[BINPRM_BUF_SIZE - 1] = '\0';
    115 +        cp = strchr(buf, '\n');
    116 +        if (cp == NULL) {
    117 +            cp = buf + BINPRM_BUF_SIZE - 1;
    118 +        }
    119 +        *cp = '\0';
    120 +        while (cp > buf) {
    121 +            cp--;
    122 +            if ((*cp == ' ') || (*cp == '\t')) {
    123 +                *cp = '\0';
    124 +            } else {
    125 +                break;
    126 +            }
    127 +        }
    128 +        for (cp = buf + 2; (*cp == ' ') || (*cp == '\t'); cp++) {
    129 +            /* nothing */ ;
    130 +        }
    131 +        if (*cp == '\0') {
    132 +            return -ENOEXEC; /* No interpreter name found */
    133 +        }
    134 +        i_name = cp;
    135 +        i_arg = NULL;
    136 +        for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
    137 +            /* nothing */ ;
    138 +        }
    139 +        while ((*cp == ' ') || (*cp == '\t')) {
    140 +            *cp++ = '\0';
    141 +        }
    142 +        if (*cp) {
    143 +            i_arg = cp;
    144 +        }
    145 +
    146 +        if (i_arg) {
    147 +            offset += 2;
    148 +        } else {
    149 +            offset += 1;
    150 +        }
    151 +    }
    152 +
    153 +    new_argp = alloca((argc + offset + 1) * sizeof(void *));
    154 +
    155 +    /* Copy the original arguments with offset */
    156 +    for (i = 0; i < argc; i++) {
    157 +        new_argp[i + offset] = argv[i];
    158 +    }
    159 +
    160 +    new_argp[0] = strdup(qemu_execve_path);
    161 +    new_argp[1] = strdup("--execve");
    162 +    new_argp[2] = strdup(qemu_execve_path);
    163 +    new_argp[3] = strdup("-0");
    164 +    new_argp[offset] = filename;
    165 +    new_argp[argc + offset] = NULL;
    166 +
    167 +    if (i_name) {
    168 +        new_argp[4] = i_name;
    169 +        new_argp[5] = i_name;
    170 +
    171 +        if (i_arg) {
    172 +            new_argp[6] = i_arg;
    173 +        }
    174 +    } else {
    175 +        new_argp[4] = argv[0];
    176 +    }
    177 +
    178 +    return get_errno(safe_execve(qemu_execve_path, new_argp, envp));
    179 +}
    180 +
    181  static int do_execv(CPUArchState *cpu_env, int dirfd,
    182                      abi_long pathname, abi_long guest_argp,
    183                      abi_long guest_envp, int flags, bool is_execveat)
    184 @@ -8745,17 +8877,6 @@ static int do_execv(CPUArchState *cpu_env, int dirfd,
    185      }
    186      *q = NULL;
    187  
    188 -    /*
    189 -     * Although execve() is not an interruptible syscall it is
    190 -     * a special case where we must use the safe_syscall wrapper:
    191 -     * if we allow a signal to happen before we make the host
    192 -     * syscall then we will 'lose' it, because at the point of
    193 -     * execve the process leaves QEMU's control. So we use the
    194 -     * safe syscall wrapper to ensure that we either take the
    195 -     * signal as a guest signal, or else it does not happen
    196 -     * before the execve completes and makes it the other
    197 -     * program's problem.
    198 -     */
    199      p = lock_user_string(pathname);
    200      if (!p) {
    201          goto execve_efault;
    202 @@ -8765,10 +8886,7 @@ static int do_execv(CPUArchState *cpu_env, int dirfd,
    203      if (is_proc_myself(p, "exe")) {
    204          exe = exec_path;
    205      }
    206 -    ret = is_execveat
    207 -        ? safe_execveat(dirfd, exe, argp, envp, flags)
    208 -        : safe_execve(exe, argp, envp);
    209 -    ret = get_errno(ret);
    210 +    ret = qemu_execve(dirfd, exe, argp, envp, flags, is_execveat);
    211  
    212      unlock_user(p, pathname, 0);
    213  
    214 diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h
    215 index c63ef45fc7..125e499370 100644
    216 --- a/linux-user/user-internals.h
    217 +++ b/linux-user/user-internals.h
    218 @@ -28,6 +28,7 @@ void init_task_state(TaskState *ts);
    219  void task_settid(TaskState *);
    220  void stop_all_tasks(void);
    221  extern const char *qemu_uname_release;
    222 +extern const char *qemu_execve_path;
    223  extern unsigned long mmap_min_addr;
    224  
    225  typedef struct IOCTLEntry IOCTLEntry;
    226 diff --git a/target/i386/cpu.c b/target/i386/cpu.c
    227 index 97ad229d8b..408db3365d 100644
    228 --- a/target/i386/cpu.c
    229 +++ b/target/i386/cpu.c
    230 @@ -1759,6 +1759,7 @@ typedef struct X86CPUDefinition {
    231      int family;
    232      int model;
    233      int stepping;
    234 +    int brand_id;
    235      FeatureWordArray features;
    236      const char *model_id;
    237      const CPUCaches *const cache_info;
    238 @@ -2444,6 +2445,54 @@ static const X86CPUDefinition builtin_x86_defs[] = {
    239          .xlevel = 0,
    240          .model_id = "",
    241      },
    242 +    {
    243 +        /* http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0000F4A_K8_Clawhammer_CPUID.txt */
    244 +        .name = "athlon-64",
    245 +        .level = 1,
    246 +        .vendor = CPUID_VENDOR_AMD,
    247 +        .family = 15,
    248 +        .model = 4,
    249 +        .stepping = 10,
    250 +        .features[FEAT_1_EDX] =
    251 +            CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE |
    252 +            CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE |
    253 +            CPUID_CX8 | CPUID_APIC | CPUID_SEP |
    254 +            CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV |
    255 +            CPUID_PAT | CPUID_PSE36 | /*no: CPUID_PN |*/ CPUID_CLFLUSH |
    256 +            /*no: CPUID_DTS | CPUID_ACPI |*/ CPUID_MMX |
    257 +            CPUID_FXSR | CPUID_SSE | CPUID_SSE2,
    258 +        .features[FEAT_8000_0001_EDX] =
    259 +            (CPUID_EXT2_FPU | CPUID_EXT2_VME | CPUID_EXT2_DE | CPUID_EXT2_PSE |
    260 +             CPUID_EXT2_TSC | CPUID_EXT2_MSR | CPUID_EXT2_PAE | CPUID_EXT2_MCE |
    261 +             CPUID_EXT2_CX8 | CPUID_EXT2_APIC | CPUID_EXT2_SYSCALL |
    262 +             CPUID_EXT2_MTRR | CPUID_EXT2_PGE | CPUID_EXT2_MCA | CPUID_EXT2_CMOV |
    263 +             CPUID_EXT2_PAT | CPUID_EXT2_PSE36 | /*no: CPUID_EXT2_MP */
    264 +             CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_MMX |
    265 +             CPUID_EXT2_FXSR | /*no: CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1G | CPUID_EXT2_RTDSCP*/
    266 +             CPUID_EXT2_LM | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_3DNOW) &
    267 +            ~CPUID_EXT2_AMD_ALIASES,
    268 +        /* todo cache info 0x80000005-6 */
    269 +        .features[FEAT_8000_0007_EDX] = 0x0f, /*??*/
    270 +        /*.phys_bits = 0x00003028,*/
    271 +        .xlevel = 0x80000018,
    272 +        .brand_id = 0x106,
    273 +        .model_id = "AMD Athlon(tm) 64 Processor 2800+",
    274 +    },
    275 +    {
    276 +        .name = "u3-64bit-minimal",
    277 +        .level = 1,
    278 +        .vendor = CPUID_VENDOR_AMD,
    279 +        .family = 15,
    280 +        .model = 4,
    281 +        .stepping = 10,
    282 +        .features[FEAT_1_EDX] =
    283 +        PENTIUM2_FEATURES | PPRO_FEATURES | CPUID_CLFLUSH /*sse2?*/,
    284 +        .features[FEAT_8000_0001_EDX] =
    285 +            /* NX: amd: since amd64, intel: P4 Prescott+ */
    286 +            CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | CPUID_EXT2_LM,
    287 +        .xlevel = 0x80000018,
    288 +        .model_id = "Fuck off",
    289 +    },
    290      {
    291          .name = "athlon",
    292          .level = 2,
    293 @@ -5165,6 +5214,41 @@ static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v,
    294      env->cpuid_version |= value & 0xf;
    295  }
    296  
    297 +static void x86_cpuid_version_get_brand_id(Object *obj, Visitor *v,
    298 +                                           const char *name, void *opaque,
    299 +                                           Error **errp)
    300 +{
    301 +    X86CPU *cpu = X86_CPU(obj);
    302 +    CPUX86State *env = &cpu->env;
    303 +    int64_t value;
    304 +
    305 +    value = env->cpuid_brand_id;
    306 +    visit_type_int(v, name, &value, errp);
    307 +}
    308 +
    309 +static void x86_cpuid_version_set_brand_id(Object *obj, Visitor *v,
    310 +                                           const char *name, void *opaque,
    311 +                                           Error **errp)
    312 +{
    313 +    X86CPU *cpu = X86_CPU(obj);
    314 +    CPUX86State *env = &cpu->env;
    315 +    const int64_t min = 0;
    316 +    const int64_t max = 0xffff;
    317 +    int64_t value;
    318 +
    319 +    if (!visit_type_int(v, name, &value, errp)) {
    320 +        return;
    321 +    }
    322 +    if (value < min || value > max) {
    323 +        error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
    324 +                   name ? name : "null", value, min, max);
    325 +        return;
    326 +    }
    327 +
    328 +    env->cpuid_brand_id = value;
    329 +}
    330 +
    331 +
    332  static char *x86_cpuid_get_vendor(Object *obj, Error **errp)
    333  {
    334      X86CPU *cpu = X86_CPU(obj);
    335 @@ -5877,6 +5961,8 @@ static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model)
    336                              &error_abort);
    337      object_property_set_str(OBJECT(cpu), "model-id", def->model_id,
    338                              &error_abort);
    339 +    object_property_set_int(OBJECT(cpu), "brand-id", def->brand_id,
    340 +                            &error_abort);
    341      for (w = 0; w < FEATURE_WORDS; w++) {
    342          env->features[w] = def->features[w];
    343      }
    344 @@ -6488,7 +6574,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
    345          break;
    346      case 0x80000001:
    347          *eax = env->cpuid_version;
    348 -        *ebx = 0;
    349 +        *ebx = env->cpuid_brand_id;
    350          *ecx = env->features[FEAT_8000_0001_ECX];
    351          *edx = env->features[FEAT_8000_0001_EDX];
    352  
    353 @@ -7982,6 +8068,9 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
    354      object_class_property_add(oc, "stepping", "int",
    355                                x86_cpuid_version_get_stepping,
    356                                x86_cpuid_version_set_stepping, NULL, NULL);
    357 +    object_class_property_add(oc, "brand-id", "int",
    358 +                              x86_cpuid_version_get_brand_id,
    359 +                              x86_cpuid_version_set_brand_id, NULL, NULL);
    360      object_class_property_add_str(oc, "vendor",
    361                                    x86_cpuid_get_vendor,
    362                                    x86_cpuid_set_vendor);
    363 diff --git a/target/i386/cpu.h b/target/i386/cpu.h
    364 index e0771a1043..2b9a1aef24 100644
    365 --- a/target/i386/cpu.h
    366 +++ b/target/i386/cpu.h
    367 @@ -1803,6 +1803,7 @@ typedef struct CPUArchState {
    368      uint32_t cpuid_vendor2;
    369      uint32_t cpuid_vendor3;
    370      uint32_t cpuid_version;
    371 +    uint32_t cpuid_brand_id;
    372      FeatureWordArray features;
    373      /* Features that were explicitly enabled/disabled */
    374      FeatureWordArray user_features;