Commit 84273177f25886b3476138470280890001debcbc

Authored by Jan Kiszka
Committed by Anthony Liguori
1 parent b1631e7a

gdbstub: x86: Support for setting segment registers

This allows to set segment registers via gdb also in system emulation
mode. Basic sanity checks are applied and nothing is changed if they
fail. But screwing up the target via this interface will never be
complicated, so I avoided being too paranoid here.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
gdbstub.c
... ... @@ -563,6 +563,31 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
563 563 return 0;
564 564 }
565 565  
  566 +static int cpu_x86_gdb_load_seg(CPUState *env, int sreg, uint8_t *mem_buf)
  567 +{
  568 + uint16_t selector = ldl_p(mem_buf);
  569 +
  570 + if (selector != env->segs[sreg].selector) {
  571 +#if defined(CONFIG_USER_ONLY)
  572 + cpu_x86_load_seg(env, sreg, selector);
  573 +#else
  574 + unsigned int limit, flags;
  575 + target_ulong base;
  576 +
  577 + if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
  578 + base = selector << 4;
  579 + limit = 0xffff;
  580 + flags = 0;
  581 + } else {
  582 + if (!cpu_x86_get_descr_debug(env, selector, &base, &limit, &flags))
  583 + return 4;
  584 + }
  585 + cpu_x86_load_seg_cache(env, sreg, selector, base, limit, flags);
  586 +#endif
  587 + }
  588 + return 4;
  589 +}
  590 +
566 591 static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
567 592 {
568 593 uint32_t tmp;
... ... @@ -590,23 +615,12 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
590 615 env->eflags = ldl_p(mem_buf);
591 616 return 4;
592 617  
593   -#if defined(CONFIG_USER_ONLY)
594   -#define LOAD_SEG(index, sreg)\
595   - tmp = ldl_p(mem_buf);\
596   - if (tmp != env->segs[sreg].selector)\
597   - cpu_x86_load_seg(env, sreg, tmp);\
598   - return 4
599   -#else
600   -/* FIXME: Honor segment registers. Needs to avoid raising an exception
601   - when the selector is invalid. */
602   -#define LOAD_SEG(index, sreg) return 4
603   -#endif
604   - case IDX_SEG_REGS: LOAD_SEG(10, R_CS);
605   - case IDX_SEG_REGS + 1: LOAD_SEG(11, R_SS);
606   - case IDX_SEG_REGS + 2: LOAD_SEG(12, R_DS);
607   - case IDX_SEG_REGS + 3: LOAD_SEG(13, R_ES);
608   - case IDX_SEG_REGS + 4: LOAD_SEG(14, R_FS);
609   - case IDX_SEG_REGS + 5: LOAD_SEG(15, R_GS);
  618 + case IDX_SEG_REGS: return cpu_x86_gdb_load_seg(env, R_CS, mem_buf);
  619 + case IDX_SEG_REGS + 1: return cpu_x86_gdb_load_seg(env, R_SS, mem_buf);
  620 + case IDX_SEG_REGS + 2: return cpu_x86_gdb_load_seg(env, R_DS, mem_buf);
  621 + case IDX_SEG_REGS + 3: return cpu_x86_gdb_load_seg(env, R_ES, mem_buf);
  622 + case IDX_SEG_REGS + 4: return cpu_x86_gdb_load_seg(env, R_FS, mem_buf);
  623 + case IDX_SEG_REGS + 5: return cpu_x86_gdb_load_seg(env, R_GS, mem_buf);
610 624  
611 625 case IDX_FP_REGS + 8:
612 626 env->fpuc = ldl_p(mem_buf);
... ...
target-i386/cpu.h
... ... @@ -770,6 +770,10 @@ static inline void cpu_x86_load_seg_cache(CPUX86State *env,
770 770 }
771 771 }
772 772  
  773 +int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
  774 + target_ulong *base, unsigned int *limit,
  775 + unsigned int *flags);
  776 +
773 777 /* wrapper, just in case memory mappings must be changed */
774 778 static inline void cpu_x86_set_cpl(CPUX86State *s, int cpl)
775 779 {
... ...
target-i386/helper.c
... ... @@ -1782,6 +1782,36 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
1782 1782 }
1783 1783 }
1784 1784  
  1785 +
  1786 +int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
  1787 + target_ulong *base, unsigned int *limit,
  1788 + unsigned int *flags)
  1789 +{
  1790 + SegmentCache *dt;
  1791 + target_ulong ptr;
  1792 + uint32_t e1, e2;
  1793 + int index;
  1794 +
  1795 + if (selector & 0x4)
  1796 + dt = &env->ldt;
  1797 + else
  1798 + dt = &env->gdt;
  1799 + index = selector & ~7;
  1800 + ptr = dt->base + index;
  1801 + if ((index + 7) > dt->limit
  1802 + || cpu_memory_rw_debug(env, ptr, (uint8_t *)&e1, sizeof(e1), 0) != 0
  1803 + || cpu_memory_rw_debug(env, ptr+4, (uint8_t *)&e2, sizeof(e2), 0) != 0)
  1804 + return 0;
  1805 +
  1806 + *base = ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
  1807 + *limit = (e1 & 0xffff) | (e2 & 0x000f0000);
  1808 + if (e2 & DESC_G_MASK)
  1809 + *limit = (*limit << 12) | 0xfff;
  1810 + *flags = e2;
  1811 +
  1812 + return 1;
  1813 +}
  1814 +
1785 1815 CPUX86State *cpu_x86_init(const char *cpu_model)
1786 1816 {
1787 1817 CPUX86State *env;
... ...