mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
If PAGE_SIZE is already defined in the system (e.g. in /usr/include/limits.h header) then gcc will trigger a redefinition error because of -Werror. This patch replaces usage of PAGE_* macros with KDD_PAGE_* macros in order to avoid confusion between control domain page granularity (PAGE_* definitions) and guest domain page granularity (which is what we are dealing with here). We chose to define the KDD_PAGE_* macros instead of using XC_PAGE_* macros because (1) the code in kdd.c should not include any Xen headers and (2) to add consistency for code in both kdd.c and kdd-xen.c. Signed-off-by: Costin Lupu <costin.lupu@cs.pub.ro> Reviewed-by: Tim Deegan <tim@xen.org> Acked-by: Ian Jackson <iwj@xenproject.org>
527 lines
17 KiB
C
527 lines
17 KiB
C
/*
|
|
* kdd.h -- Structures, constants and descriptions of the Windows
|
|
* kd serial debugger protocol, for the kdd debugging stub.
|
|
*
|
|
* Tim Deegan <Tim.Deegan@citrix.com>
|
|
*
|
|
* Copyright (c) 2007-2010, Citrix Systems Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef _KDD_H_
|
|
#define _KDD_H_
|
|
|
|
#include <stdint.h>
|
|
|
|
#define PACKED __attribute__((packed))
|
|
|
|
/* We define our page related constants here in order to specifically
|
|
* avoid using the Xen page macros (this is a restriction for the code
|
|
* in kdd.c which should not include any Xen headers) and to add
|
|
* consistency for code in both kdd.c and kdd-xen.c. */
|
|
#define KDD_PAGE_SHIFT 12
|
|
#define KDD_PAGE_SIZE (1U << KDD_PAGE_SHIFT)
|
|
|
|
/*****************************************************************************
|
|
* Serial line protocol: Sender sends a 16-byte header with an optional
|
|
* payload following it. Receiver responds to each packet with an
|
|
* acknowledgment (16-byte header only).
|
|
*
|
|
* Packet headers start with ASCII "0000" and there is a trailing byte
|
|
* 0xAA after the (optional) payload. Ack headers start with ASCII
|
|
* "iiii"; no trailing byte). Each packet and ack has a major type in
|
|
* the packet header; for packets with payload, a minor type is encoded
|
|
* in ASCII in the first four bytes of the payload.
|
|
*
|
|
* Packet IDs seem to start at 0x80800000 and alternate between that and
|
|
* 0x80800001; not clear whether the client's ID is always the ID of the
|
|
* last packet from the kernel or whether they're just oscillating in
|
|
* phase. Either way there's clearly some state machine in the kernel
|
|
* that requires this exact behaviour from the client.
|
|
*
|
|
* All acks have length 0, id = id of the packet they ack.
|
|
*/
|
|
|
|
#define KDD_DIR_PKT 0x30303030 /* "0000" */
|
|
#define KDD_DIR_ACK 0x69696969 /* "iiii" */
|
|
|
|
typedef struct {
|
|
uint32_t dir; /* KDD_DIR_PKT or KDD_DIR_ACK */
|
|
uint16_t type; /* Major type. */
|
|
uint16_t len; /* Payload length, excl. header and trailing byte */
|
|
uint32_t id; /* Echoed in responses */
|
|
uint32_t sum; /* Unsigned sum of all payload bytes */
|
|
} PACKED kdd_hdr;
|
|
|
|
#define KDD_PKT_CMD 0x0002 /* Debugger commands (and replies to them) */
|
|
#define KDD_PKT_MSG 0x0003 /* Kernel messages for the user */
|
|
#define KDD_PKT_STC 0x0007 /* State change notification */
|
|
#define KDD_PKT_REG 0x000b /* Registry change notification (?) */
|
|
#define KDD_PKT_MAX 0x000b
|
|
|
|
#define KDD_ACK_OK 0x0004 /* Checksum, ID and type all fine */
|
|
#define KDD_ACK_BAD 0x0005 /* Something is bogus */
|
|
#define KDD_ACK_RST 0x0006 /* Not really an ack; one each way to resync */
|
|
|
|
|
|
/*****************************************************************************
|
|
* Debugger commands, carried over the serial line. In this protocol,
|
|
* we ignore the serial-level acking; when we talk about a response,
|
|
* it's another packet, sent after the request was acked, and which will
|
|
* itself be acked.
|
|
*
|
|
* The debugger client sends commands to the kernel, all of which have
|
|
* major type 2 and are 56 bytes long (not including the serial header).
|
|
* Not all the 56 bytes are used in every command, but the client
|
|
* doesn't bother to zero unused fields. Most commands are responded to
|
|
* by a packet with the same subtype, containing at least a status code
|
|
* to indicate success or failure.
|
|
*/
|
|
|
|
#define KDD_STATUS_SUCCESS 0x00000000
|
|
#define KDD_STATUS_FAILURE 0xc0000001
|
|
#define KDD_STATUS_PENDING 0x00000103
|
|
|
|
/* Memory access. Read commands are echoed in the response with the
|
|
* status and length_rsp fields updated, and the read data appended to the
|
|
* packet. Writes are the same, but with the data appended to the
|
|
* write command, not the response. */
|
|
|
|
#define KDD_CMD_READ_VA 0x00003130 /* "01" */
|
|
#define KDD_CMD_WRITE_VA 0x00003131 /* "11" */
|
|
#define KDD_CMD_READ_CTRL 0x00003137 /* "71" */
|
|
#define KDD_CMD_WRITE_CTRL 0x00003138 /* "81" */
|
|
#define KDD_CMD_READ_PA 0x0000313D /* "=1" */
|
|
#define KDD_CMD_WRITE_PA 0x0000313E /* ">1" */
|
|
|
|
/* Not sure what this is, but it doesn't require a response */
|
|
#define KDD_CMD_WRITE_Z 0x0000315A /* "Z1" */
|
|
|
|
typedef struct {
|
|
uint32_t u1;
|
|
uint32_t status; /* IN: STATUS_PENDING; OUT: result status. */
|
|
uint32_t u2;
|
|
uint64_t addr; /* IN: address of start of read/write */
|
|
uint32_t length_req; /* IN: bytes to read/write */
|
|
uint32_t length_rsp; /* OUT: bytes successfully read/written */
|
|
} PACKED kdd_cmd_mem;
|
|
|
|
/* CPU register access. As for memory accesses, but the data is a
|
|
* fixed-length block of register info. */
|
|
|
|
#define KDD_CMD_READ_REGS 0x00003132 /* "21" */
|
|
#define KDD_CMD_WRITE_REGS 0x00003133 /* "31" */
|
|
|
|
typedef struct {
|
|
uint16_t u1;
|
|
uint16_t cpu; /* IN: Zero-based processor ID */
|
|
uint32_t status; /* IN: STATUS_PENDING; OUT: result status. */
|
|
} PACKED kdd_cmd_regs;
|
|
|
|
#define KDD_CMD_READ_MSR 0x00003152 /* "R1" */
|
|
#define KDD_CMD_WRITE_MSR 0x00003153 /* "S1" */
|
|
|
|
typedef struct {
|
|
uint32_t u1;
|
|
uint32_t status; /* IN: STATUS_PENDING; OUT: result status. */
|
|
uint32_t u2;
|
|
uint32_t msr; /* IN/OUT: MSR number */
|
|
uint64_t val; /* IN/OUT: MSR contents */
|
|
} PACKED kdd_cmd_msr;
|
|
|
|
/* Breakpoint commands. */
|
|
|
|
#define KDD_CMD_SOFT_BP 0x00003135 /* "51" */
|
|
|
|
typedef struct {
|
|
uint32_t u1;
|
|
uint32_t status; /* IN: STATUS_PENDING; OUT: result status. */
|
|
uint32_t u2;
|
|
uint32_t bp; /* IN: ID of breakpoint to operate on */
|
|
} PACKED kdd_cmd_soft_bp;
|
|
|
|
#define KDD_CMD_HARD_BP 0x0000315C /* "\1" */
|
|
|
|
typedef struct {
|
|
uint32_t u1;
|
|
uint32_t status; /* IN: STATUS_PENDING; OUT: result status. */
|
|
uint32_t u2;
|
|
uint64_t address; /* IN: Address to trap on */
|
|
uint64_t u3;
|
|
uint64_t u4;
|
|
uint64_t u5;
|
|
uint64_t u6;
|
|
} PACKED kdd_cmd_hard_bp;
|
|
|
|
/* Flow control commands. These commands are _not_ responded to. */
|
|
|
|
#define KDD_CMD_CONT1 0x00003136 /* "61" */
|
|
#define KDD_CMD_CONT2 0x0000313c /* "<1" */
|
|
|
|
#define KDD_DBG_EXCEPTION_HANDLED 0x00010001
|
|
#define KDD_DBG_CONTINUE 0x00010002
|
|
|
|
typedef struct {
|
|
uint32_t u1;
|
|
uint32_t reason1; /* IN: KDD_DBG_* */
|
|
uint32_t u2;
|
|
uint64_t reason2; /* IN: always same as reason1 */
|
|
} PACKED kdd_cmd_cont;
|
|
|
|
/* Handshake command. */
|
|
|
|
#define KDD_CMD_SHAKE 0x00003146 /* "F1" */
|
|
|
|
#define KDD_MACH_x32 0x014c
|
|
#define KDD_MACH_x64 0x8664
|
|
|
|
#define KDD_FLAGS_MP 0x0001
|
|
#define KDD_FLAGS_64 0x0008
|
|
|
|
typedef struct {
|
|
uint32_t u1;
|
|
uint32_t status; /* IN: STATUS_PENDING; OUT: result status. */
|
|
uint32_t u2;
|
|
uint16_t v_major; /* OUT: OS major version (0xf for NT) */
|
|
uint16_t v_minor; /* OUT: OS minor version (NT build number) */
|
|
uint16_t proto; /* OUT: Protocol version (6) */
|
|
uint16_t flags; /* OUT: Some flags (at least 0x3) */
|
|
uint16_t machine; /* OUT: Machine type */
|
|
uint8_t pkts; /* OUT: Number of packet types understood */
|
|
uint8_t states; /* OUT: Number of state-change types used */
|
|
uint8_t manips; /* OUT: number of "manipulation" types used */
|
|
uint8_t u3[3];
|
|
int64_t kern_addr; /* OUT: KernBase */
|
|
int64_t mods_addr; /* OUT: PsLoadedModuleList */
|
|
int64_t data_addr; /* OUT: DebuggerDataList */
|
|
} PACKED kdd_cmd_shake;
|
|
|
|
/* Change active CPU. This command is _not_ responded to */
|
|
|
|
#define KDD_CMD_SETCPU 0x00003150 /* "P1" */
|
|
|
|
typedef struct {
|
|
uint16_t u1;
|
|
uint16_t cpu; /* IN: Zero-based processor ID */
|
|
uint32_t status; /* IN: STATUS_PENDING */
|
|
} PACKED kdd_cmd_setcpu;
|
|
|
|
typedef struct {
|
|
uint32_t subtype; /* IN: KDD_CMD_x */
|
|
union {
|
|
kdd_cmd_mem mem;
|
|
kdd_cmd_regs regs;
|
|
kdd_cmd_msr msr;
|
|
kdd_cmd_soft_bp sbp;
|
|
kdd_cmd_hard_bp hbp;
|
|
kdd_cmd_cont cont;
|
|
kdd_cmd_shake shake;
|
|
kdd_cmd_setcpu setcpu;
|
|
uint8_t pad[52];
|
|
};
|
|
uint8_t data[0];
|
|
} PACKED kdd_cmd;
|
|
|
|
|
|
/*****************************************************************************
|
|
* Kernel messages to the debugger. The debugger does not respond to these
|
|
* beyond ACKing them and printing approprate things on the debugger
|
|
* console.
|
|
*/
|
|
|
|
/* Messages for the console */
|
|
|
|
#define KDD_MSG_PRINT 0x00003230 /* "02" */
|
|
|
|
typedef struct {
|
|
uint32_t subtype; /* KDD_MSG_PRINT */
|
|
uint32_t u1;
|
|
uint32_t length; /* Length in bytes of trailing string */
|
|
uint32_t u2;
|
|
uint8_t string[0]; /* Non-terminated character string */
|
|
} PACKED kdd_msg;
|
|
|
|
/* Registry updates (Hive loads?) */
|
|
|
|
#define KDD_REG_CHANGE 0x00003430 /* "04" */
|
|
|
|
typedef struct {
|
|
uint32_t subtype; /* KDD_REG_CHANGE */
|
|
uint32_t u1[15];
|
|
uint16_t string[0]; /* Null-terminated wchar string */
|
|
} PACKED kdd_reg;
|
|
|
|
/* State changes. After sending a state-change message the kernel halts
|
|
* until it receives a continue command from the debugger. */
|
|
|
|
#define KDD_STC_STOP 0x00003030 /* "00" : Bug-check */
|
|
#define KDD_STC_LOAD 0x00003031 /* "01" : Loaded a module */
|
|
|
|
#define KDD_STC_STATUS_BREAKPOINT 0x80000003
|
|
|
|
typedef struct {
|
|
uint16_t u1;
|
|
uint16_t cpu; /* Zero-based processor ID */
|
|
uint32_t ncpus; /* Number of processors */
|
|
uint32_t u2;
|
|
int64_t kthread; /* Kernel thread structure */
|
|
int64_t rip1; /* Instruction pointer, sign-extended */
|
|
uint64_t status; /* KDD_STC_STATUS_x */
|
|
uint64_t u3;
|
|
int64_t rip2; /* Same as rip1 */
|
|
uint64_t nparams; /* Number of stopcode parameters */
|
|
uint64_t params[15]; /* Stopcode parameters */
|
|
uint64_t first_chance; /* OS exn handlers not yet been run? */
|
|
uint32_t u4[2];
|
|
uint32_t ilen; /* Number of bytes of instruction following */
|
|
uint8_t inst[36]; /* VA contents from %eip onwards */
|
|
} PACKED kdd_stc_stop;
|
|
|
|
typedef struct {
|
|
uint32_t u1[3];
|
|
uint64_t u2;
|
|
uint64_t rip; /* Instruction pointer, sign-extended */
|
|
uint64_t u3[26];
|
|
uint8_t path[0]; /* Null-terminated ASCII path to loaded mod. */
|
|
} PACKED kdd_stc_load;
|
|
|
|
typedef struct {
|
|
uint32_t subtype; /* KDD_STC_x */
|
|
union {
|
|
kdd_stc_stop stop;
|
|
kdd_stc_load load;
|
|
};
|
|
} PACKED kdd_stc;
|
|
|
|
|
|
/*****************************************************************************
|
|
* Overall packet type
|
|
*/
|
|
|
|
typedef struct {
|
|
kdd_hdr h; /* Major type disambiguates union below */
|
|
union {
|
|
kdd_cmd cmd;
|
|
kdd_msg msg;
|
|
kdd_reg reg;
|
|
kdd_stc stc;
|
|
uint8_t payload[65536];
|
|
};
|
|
} PACKED kdd_pkt;
|
|
|
|
|
|
/*****************************************************************************
|
|
* Processor state layouts
|
|
*/
|
|
|
|
/* User-visible register files */
|
|
typedef union {
|
|
uint32_t pad[179];
|
|
struct {
|
|
uint32_t u1[7]; /* Flags, DRx?? */
|
|
uint8_t fp[112]; /* FP save state (why 112 not 108?) */
|
|
int32_t gs;
|
|
int32_t fs;
|
|
int32_t es;
|
|
int32_t ds;
|
|
int32_t edi;
|
|
int32_t esi;
|
|
int32_t ebx;
|
|
int32_t edx;
|
|
int32_t ecx;
|
|
int32_t eax;
|
|
int32_t ebp;
|
|
int32_t eip;
|
|
int32_t cs;
|
|
int32_t eflags;
|
|
int32_t esp;
|
|
int32_t ss;
|
|
uint32_t sp2[37]; /* More 0x20202020. fp? */
|
|
uint32_t sp3; /* 0x00202020 */
|
|
};
|
|
} PACKED kdd_regs_x86_32;
|
|
|
|
typedef union {
|
|
uint64_t pad[154];
|
|
struct {
|
|
|
|
uint64_t u1[7];
|
|
|
|
uint16_t cs; //2*1c
|
|
uint16_t ds;
|
|
uint16_t es;
|
|
uint16_t fs;
|
|
uint16_t gs;
|
|
uint16_t ss;
|
|
uint32_t rflags;
|
|
uint64_t dr0;
|
|
uint64_t dr1;
|
|
uint64_t dr2;
|
|
uint64_t dr3;
|
|
uint64_t dr6;
|
|
uint64_t dr7;
|
|
int64_t rax;
|
|
int64_t rcx;
|
|
int64_t rdx;
|
|
int64_t rbx;
|
|
int64_t rsp;
|
|
int64_t rbp;
|
|
int64_t rsi;
|
|
int64_t rdi;
|
|
int64_t r8;
|
|
int64_t r9;
|
|
int64_t r10;
|
|
int64_t r11;
|
|
int64_t r12;
|
|
int64_t r13;
|
|
int64_t r14;
|
|
int64_t r15;
|
|
int64_t rip; //2*7c
|
|
|
|
uint64_t u2[32];
|
|
|
|
uint8_t fp[512]; // fp @2*100 .. 150 (+ more??)
|
|
|
|
uint64_t u3[26];
|
|
};
|
|
} PACKED kdd_regs_x86_64;
|
|
|
|
typedef union {
|
|
kdd_regs_x86_32 r32;
|
|
kdd_regs_x86_64 r64;
|
|
} PACKED kdd_regs;
|
|
|
|
/* System registers */
|
|
typedef struct {
|
|
uint32_t cr0;
|
|
uint32_t cr2;
|
|
uint32_t cr3;
|
|
uint32_t cr4;
|
|
uint32_t dr0;
|
|
uint32_t dr1;
|
|
uint32_t dr2;
|
|
uint32_t dr3;
|
|
uint32_t dr6;
|
|
uint32_t dr7;
|
|
uint16_t gdt_pad;
|
|
uint16_t gdt_limit;
|
|
uint32_t gdt_base;
|
|
uint16_t idt_pad;
|
|
uint16_t idt_limit;
|
|
uint32_t idt_base;
|
|
uint16_t tss_sel;
|
|
uint16_t ldt_sel;
|
|
uint8_t u1[24];
|
|
} PACKED kdd_ctrl_x86_32;
|
|
|
|
typedef struct {
|
|
uint64_t cr0;
|
|
uint64_t cr2;
|
|
uint64_t cr3;
|
|
uint64_t cr4;
|
|
uint64_t dr0;
|
|
uint64_t dr1;
|
|
uint64_t dr2;
|
|
uint64_t dr3;
|
|
uint64_t dr6;
|
|
uint64_t dr7;
|
|
uint8_t gdt_pad[6];
|
|
uint16_t gdt_limit;
|
|
uint64_t gdt_base;
|
|
uint8_t idt_pad[6];
|
|
uint16_t idt_limit;
|
|
uint64_t idt_base;
|
|
uint16_t tss_sel;
|
|
uint16_t ldt_sel;
|
|
uint8_t u1[44];
|
|
uint64_t cr8;
|
|
uint8_t u2[40];
|
|
uint64_t efer; // XXX find out where EFER actually goes
|
|
} PACKED kdd_ctrl_x86_64;
|
|
|
|
typedef union {
|
|
kdd_ctrl_x86_32 c32;
|
|
kdd_ctrl_x86_64 c64;
|
|
} kdd_ctrl;
|
|
|
|
/*****************************************************************************
|
|
* Functions required from the emulator/hypervisor for the stub to work.
|
|
*/
|
|
|
|
typedef struct kdd_guest kdd_guest;
|
|
|
|
/* Init and teardown guest-specific state */
|
|
extern kdd_guest *kdd_guest_init(char *arg, FILE *log, int verbosity);
|
|
extern void kdd_guest_teardown(kdd_guest *g);
|
|
extern char *kdd_guest_identify(kdd_guest *g);
|
|
|
|
/* Halt and restart the running guest */
|
|
extern void kdd_halt(kdd_guest *g);
|
|
extern void kdd_run(kdd_guest *g);
|
|
|
|
/* How many CPUs are there? */
|
|
extern int kdd_count_cpus(kdd_guest *g);
|
|
|
|
/* Accessor for guest physical memory, returning bytes read/written */
|
|
extern uint32_t kdd_access_physical(kdd_guest *g, uint64_t addr,
|
|
uint32_t len, uint8_t *buf, int write);
|
|
|
|
/* Accessors for guest registers, returning 0 for success */
|
|
extern int kdd_get_regs(kdd_guest *g, int cpuid, kdd_regs *r, int w64);
|
|
extern int kdd_set_regs(kdd_guest *g, int cpuid, kdd_regs *r, int w64);
|
|
|
|
/* Accessors for guest control registers, returning 0 for success */
|
|
extern int kdd_get_ctrl(kdd_guest *g, int cpuid, kdd_ctrl *ctrl, int w64);
|
|
extern int kdd_set_ctrl(kdd_guest *g, int cpuid, kdd_ctrl *ctrl, int w64);
|
|
|
|
/* Accessors for guest MSRs, returning 0 for success */
|
|
extern int kdd_wrmsr(kdd_guest *g, int cpuid, uint32_t msr, uint64_t value);
|
|
extern int kdd_rdmsr(kdd_guest *g, int cpuid, uint32_t msr, uint64_t *value);
|
|
|
|
|
|
/*****************************************************************************
|
|
* Logfile usefulness
|
|
*/
|
|
|
|
/* Verbosity:
|
|
* 0: errors (default)
|
|
* 1: operations
|
|
* 2: packets
|
|
* 3: _everything_ */
|
|
|
|
#define KDD_LOG_IF(_v, _s, _fmt, _a...) do { \
|
|
if ((_s)->verbosity >= (_v)) { \
|
|
fprintf((_s)->log, (_fmt), ##_a); \
|
|
(void) fflush((_s)->log); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define KDD_LOG(_s, _fmt, _a...) KDD_LOG_IF(1, (_s), (_fmt), ##_a)
|
|
#define KDD_DEBUG(_s, _fmt, _a...) KDD_LOG_IF(3, (_s), (_fmt), ##_a)
|
|
|
|
#endif /* _KDD_H_ */
|