141 lines
3.1 KiB
C
141 lines
3.1 KiB
C
/*
|
|
* $QNXLicenseC:
|
|
* Copyright 2007, QNX Software Systems. All Rights Reserved.
|
|
*
|
|
* You must obtain a written license from and pay applicable license fees to QNX
|
|
* Software Systems before you may reproduce, modify or distribute this software,
|
|
* or any work that includes all or part of this software. Free development
|
|
* licenses are available for evaluation and non-commercial purposes. For more
|
|
* information visit http://licensing.qnx.com or email licensing@qnx.com.
|
|
*
|
|
* This file may contain contributions from others. Please review this entire
|
|
* file for other proprietary rights or license notices, as well as the QNX
|
|
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
|
|
* for other information.
|
|
* $
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "kdserver.h"
|
|
#include <x86/cpu.h>
|
|
#include <x86/context.h>
|
|
|
|
/*
|
|
Define a structure used for communication to a GDB client
|
|
*/
|
|
typedef struct {
|
|
int eax, ecx, edx, ebx, uesp, ebp, esi, edi, eip, efl;
|
|
int cs, ss, ds, es, fs, gs;
|
|
} x86_gdb_regs;
|
|
|
|
|
|
static int
|
|
x86_init(int elf_cpu) {
|
|
switch(elf_cpu) {
|
|
case EM_386:
|
|
case EM_486:
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
if(note->cpu_info) {
|
|
// PAE enabled
|
|
cpu->pgtbl_size = 0x4000;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int
|
|
x86_v2p(uintptr_t vaddr, paddr64_t *paddrp, unsigned *lenp) {
|
|
uint64_t pde;
|
|
uint64_t pte;
|
|
paddr64_t paddr;
|
|
unsigned offset;
|
|
unsigned page_size;
|
|
|
|
// consult the page table...
|
|
if(note->cpu_info) {
|
|
// PAE enabled
|
|
pde = endian_native64(((uint64_t *)pgtbl)[vaddr >> 21]);
|
|
page_size = 2*1024*1024;
|
|
} else {
|
|
pde = endian_native32(((uint32_t *)pgtbl)[vaddr >> 22]);
|
|
page_size = 4*1024*1024;
|
|
}
|
|
if(!(pde & X86_PDE_PRESENT)) {
|
|
return 0;
|
|
}
|
|
if(!(pde & X86_PDE_PS)) {
|
|
// 4K page
|
|
page_size = 0x1000;
|
|
paddr = pde & ~(X86_PDE_NX | (page_size-1));
|
|
if(note->cpu_info) {
|
|
//PAE enabled
|
|
paddr += ((vaddr >> 12) & 0x1ff)*sizeof(uint64_t);
|
|
if(core_read_paddr(paddr, &pte, sizeof(pte)) != sizeof(pte)) {
|
|
fprintf( stderr, "PAE core_readmem of %llx failed\n", paddr );
|
|
return 0;
|
|
}
|
|
pte = endian_native64(pte);
|
|
} else {
|
|
uint32_t pte32;
|
|
|
|
paddr += ((vaddr >> 12) & 0x3ff)*sizeof(uint32_t);
|
|
if(core_read_paddr(paddr, &pte32, sizeof(pte32)) != sizeof(pte32)) {
|
|
fprintf( stderr, "core_readmem of %llx failed\n", paddr );
|
|
return 0;
|
|
}
|
|
pte = endian_native32(pte32);
|
|
}
|
|
paddr = pte & ~(X86_PDE_NX | (page_size-1));
|
|
if(!(pte & X86_PTE_PRESENT)) {
|
|
return 0;
|
|
}
|
|
} else {
|
|
paddr = pde & ~(X86_PDE_NX | (page_size-1));
|
|
}
|
|
offset = vaddr & (page_size - 1);
|
|
*paddrp = paddr | offset;
|
|
*lenp = page_size - offset;
|
|
return 1;
|
|
}
|
|
|
|
|
|
static void
|
|
x86_cvt_regset(const void *in, void *out) {
|
|
const X86_CPU_REGISTERS *ctx = in;
|
|
x86_gdb_regs *gdb = out;
|
|
|
|
gdb->eax = ctx->eax;
|
|
gdb->ebx = ctx->ebx;
|
|
gdb->ecx = ctx->ecx;
|
|
gdb->edx = ctx->edx;
|
|
gdb->esi = ctx->esi;
|
|
gdb->edi = ctx->edi;
|
|
gdb->ebp = ctx->ebp;
|
|
gdb->uesp = ctx->esp;
|
|
gdb->efl = ctx->efl;
|
|
gdb->eip = ctx->eip;
|
|
gdb->cs = ctx->cs;
|
|
gdb->ds = 0;
|
|
gdb->ss = ctx->ss;
|
|
gdb->es = 0;
|
|
gdb->fs = 0;
|
|
gdb->gs = 0;
|
|
}
|
|
|
|
|
|
struct cpuinfo cpu_x86 = {
|
|
x86_init,
|
|
x86_v2p,
|
|
x86_cvt_regset,
|
|
0x1000,
|
|
sizeof(x86_gdb_regs),
|
|
sizeof(uint32_t)
|
|
};
|