qemu/bsd-user/x86_64/target_arch_cpu.h
<<
>>
Prefs
   1/*
   2 *  x86_64 cpu init and loop
   3 *
   4 *
   5 *  This program is free software; you can redistribute it and/or modify
   6 *  it under the terms of the GNU General Public License as published by
   7 *  the Free Software Foundation; either version 2 of the License, or
   8 *  (at your option) any later version.
   9 *
  10 *  This program is distributed in the hope that it will be useful,
  11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 *  GNU General Public License for more details.
  14 *
  15 *  You should have received a copy of the GNU General Public License
  16 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  17 */
  18
  19#ifndef TARGET_ARCH_CPU_H
  20#define TARGET_ARCH_CPU_H
  21
  22#include "target_arch.h"
  23#include "signal-common.h"
  24
  25#define TARGET_DEFAULT_CPU_MODEL "qemu64"
  26
  27static inline void target_cpu_init(CPUX86State *env,
  28        struct target_pt_regs *regs)
  29{
  30    uint64_t *gdt_table;
  31
  32    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
  33    env->hflags |= HF_PE_MASK | HF_CPL_MASK;
  34    if (env->features[FEAT_1_EDX] & CPUID_SSE) {
  35        env->cr[4] |= CR4_OSFXSR_MASK;
  36        env->hflags |= HF_OSFXSR_MASK;
  37    }
  38
  39    /* enable 64 bit mode if possible */
  40    if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
  41        fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
  42        exit(1);
  43    }
  44    env->cr[4] |= CR4_PAE_MASK;
  45    env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
  46    env->hflags |= HF_LMA_MASK;
  47
  48    /* flags setup : we activate the IRQs by default as in user mode */
  49    env->eflags |= IF_MASK;
  50
  51    /* register setup */
  52    env->regs[R_EAX] = regs->rax;
  53    env->regs[R_EBX] = regs->rbx;
  54    env->regs[R_ECX] = regs->rcx;
  55    env->regs[R_EDX] = regs->rdx;
  56    env->regs[R_ESI] = regs->rsi;
  57    env->regs[R_EDI] = regs->rdi;
  58    env->regs[R_EBP] = regs->rbp;
  59    env->regs[R_ESP] = regs->rsp;
  60    env->eip = regs->rip;
  61
  62    /* interrupt setup */
  63    env->idt.limit = 511;
  64
  65    env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
  66        PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  67    bsd_x86_64_set_idt_base(env->idt.base);
  68    bsd_x86_64_set_idt(0, 0);
  69    bsd_x86_64_set_idt(1, 0);
  70    bsd_x86_64_set_idt(2, 0);
  71    bsd_x86_64_set_idt(3, 3);
  72    bsd_x86_64_set_idt(4, 3);
  73    bsd_x86_64_set_idt(5, 0);
  74    bsd_x86_64_set_idt(6, 0);
  75    bsd_x86_64_set_idt(7, 0);
  76    bsd_x86_64_set_idt(8, 0);
  77    bsd_x86_64_set_idt(9, 0);
  78    bsd_x86_64_set_idt(10, 0);
  79    bsd_x86_64_set_idt(11, 0);
  80    bsd_x86_64_set_idt(12, 0);
  81    bsd_x86_64_set_idt(13, 0);
  82    bsd_x86_64_set_idt(14, 0);
  83    bsd_x86_64_set_idt(15, 0);
  84    bsd_x86_64_set_idt(16, 0);
  85    bsd_x86_64_set_idt(17, 0);
  86    bsd_x86_64_set_idt(18, 0);
  87    bsd_x86_64_set_idt(19, 0);
  88    bsd_x86_64_set_idt(0x80, 3);
  89
  90    /* segment setup */
  91    env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
  92            PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  93    env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
  94    gdt_table = g2h_untagged(env->gdt.base);
  95
  96    /* 64 bit code segment */
  97    bsd_x86_64_write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
  98            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | DESC_L_MASK
  99            | (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
 100
 101    bsd_x86_64_write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
 102            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
 103            (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
 104
 105    cpu_x86_load_seg(env, R_CS, __USER_CS);
 106    cpu_x86_load_seg(env, R_SS, __USER_DS);
 107    cpu_x86_load_seg(env, R_DS, 0);
 108    cpu_x86_load_seg(env, R_ES, 0);
 109    cpu_x86_load_seg(env, R_FS, 0);
 110    cpu_x86_load_seg(env, R_GS, 0);
 111}
 112
 113static inline void target_cpu_loop(CPUX86State *env)
 114{
 115    CPUState *cs = env_cpu(env);
 116    int trapnr;
 117    abi_ulong pc;
 118    /* target_siginfo_t info; */
 119
 120    for (;;) {
 121        cpu_exec_start(cs);
 122        trapnr = cpu_exec(cs);
 123        cpu_exec_end(cs);
 124        process_queued_cpu_work(cs);
 125
 126        switch (trapnr) {
 127        case EXCP_SYSCALL:
 128            /* syscall from syscall instruction */
 129            env->regs[R_EAX] = do_freebsd_syscall(env,
 130                                                  env->regs[R_EAX],
 131                                                  env->regs[R_EDI],
 132                                                  env->regs[R_ESI],
 133                                                  env->regs[R_EDX],
 134                                                  env->regs[R_ECX],
 135                                                  env->regs[8],
 136                                                  env->regs[9], 0, 0);
 137            env->eip = env->exception_next_eip;
 138            if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
 139                env->regs[R_EAX] = -env->regs[R_EAX];
 140                env->eflags |= CC_C;
 141            } else {
 142                env->eflags &= ~CC_C;
 143            }
 144            break;
 145
 146        case EXCP_INTERRUPT:
 147            /* just indicate that signals should be handled asap */
 148            break;
 149
 150        case EXCP_ATOMIC:
 151            cpu_exec_step_atomic(cs);
 152            break;
 153
 154        default:
 155            pc = env->segs[R_CS].base + env->eip;
 156            fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - "
 157                    "aborting\n", (long)pc, trapnr);
 158            abort();
 159        }
 160        process_pending_signals(env);
 161    }
 162}
 163
 164static inline void target_cpu_clone_regs(CPUX86State *env, target_ulong newsp)
 165{
 166    if (newsp) {
 167        env->regs[R_ESP] = newsp;
 168    }
 169    env->regs[R_EAX] = 0;
 170}
 171
 172static inline void target_cpu_reset(CPUArchState *env)
 173{
 174    cpu_reset(env_cpu(env));
 175}
 176
 177#endif /* TARGET_ARCH_CPU_H */
 178