nv2a: Start using tracing infrastructure for logging

This commit is contained in:
Matt Borgerson 2022-01-31 22:23:15 -07:00 committed by mborgerson
parent a13f3f48a2
commit be23a674f3
21 changed files with 266 additions and 280 deletions

View File

@ -165,7 +165,7 @@ done
target="qemu-system-i386"
if test ! -z "$debug"; then
build_cflags='-O0 -g -DXEMU_DEBUG_BUILD=1'
opts="--enable-debug"
opts="--enable-debug --enable-trace-backends=log"
else
opts="--enable-lto"
fi

View File

@ -36,7 +36,6 @@
# define NV2A_DPRINTF(format, ...) do { } while (0)
#endif
// #define DEBUG_NV2A_REG
// #define DEBUG_NV2A_GL
#ifdef DEBUG_NV2A_GL

View File

@ -21,9 +21,6 @@
#include "hw/xbox/nv2a/nv2a_int.h"
#define DBG_IRQ 0
#define DBG_DMA 0
void nv2a_update_irq(NV2AState *d)
{
/* PFIFO */
@ -48,7 +45,7 @@ void nv2a_update_irq(NV2AState *d)
}
if (d->pmc.pending_interrupts && d->pmc.enabled_interrupts) {
NV2A_XPRINTF(DBG_IRQ, "raise irq\n");
trace_nv2a_irq(d->pmc.pending_interrupts);
pci_irq_assert(PCI_DEVICE(d));
} else {
pci_irq_deassert(PCI_DEVICE(d));
@ -77,10 +74,8 @@ void *nv_dma_map(NV2AState *d, hwaddr dma_obj_address, hwaddr *len)
DMAObject dma = nv_dma_load(d, dma_obj_address);
/* TODO: Handle targets and classes properly */
NV2A_XPRINTF(DBG_DMA,
"dma_map %" HWADDR_PRIx " - %x, %x, %" HWADDR_PRIx " %" HWADDR_PRIx "\n",
dma_obj_address,
dma.dma_class, dma.dma_target, dma.address, dma.limit);
trace_nv2a_dma_map(dma_obj_address, dma.dma_class, dma.dma_target,
dma.address, dma.limit);
dma.address &= 0x07FFFFFF;
assert(dma.address < memory_region_size(d->vram));
@ -89,75 +84,36 @@ void *nv_dma_map(NV2AState *d, hwaddr dma_obj_address, hwaddr *len)
return d->vram_ptr + dma.address;
}
const struct NV2ABlockInfo blocktable[] = {
#define ENTRY(NAME, OFFSET, SIZE, RDFUNC, WRFUNC) \
[NV_##NAME] = { \
.name = #NAME, \
.offset = OFFSET, \
.size = SIZE, \
.ops = { .read = RDFUNC, .write = WRFUNC }, \
const NV2ABlockInfo blocktable[NV_NUM_BLOCKS] = {
#define ENTRY(NAME, LNAME, OFFSET, SIZE) [NV_##NAME] = { \
.name = #NAME, \
.offset = OFFSET, \
.size = SIZE, \
.ops = { .read = LNAME ## _read, .write = LNAME ## _write }, \
}
ENTRY(PMC, 0x000000, 0x001000, pmc_read, pmc_write),
ENTRY(PBUS, 0x001000, 0x001000, pbus_read, pbus_write),
ENTRY(PFIFO, 0x002000, 0x002000, pfifo_read, pfifo_write),
ENTRY(PRMA, 0x007000, 0x001000, prma_read, prma_write),
ENTRY(PVIDEO, 0x008000, 0x001000, pvideo_read, pvideo_write),
ENTRY(PTIMER, 0x009000, 0x001000, ptimer_read, ptimer_write),
ENTRY(PCOUNTER, 0x00a000, 0x001000, pcounter_read, pcounter_write),
ENTRY(PVPE, 0x00b000, 0x001000, pvpe_read, pvpe_write),
ENTRY(PTV, 0x00d000, 0x001000, ptv_read, ptv_write),
ENTRY(PRMFB, 0x0a0000, 0x020000, prmfb_read, prmfb_write),
ENTRY(PRMVIO, 0x0c0000, 0x001000, prmvio_read, prmvio_write),
ENTRY(PFB, 0x100000, 0x001000, pfb_read, pfb_write),
ENTRY(PSTRAPS, 0x101000, 0x001000, pstraps_read, pstraps_write),
ENTRY(PGRAPH, 0x400000, 0x002000, pgraph_read, pgraph_write),
ENTRY(PCRTC, 0x600000, 0x001000, pcrtc_read, pcrtc_write),
ENTRY(PRMCIO, 0x601000, 0x001000, prmcio_read, prmcio_write),
ENTRY(PRAMDAC, 0x680000, 0x001000, pramdac_read, pramdac_write),
ENTRY(PRMDIO, 0x681000, 0x001000, prmdio_read, prmdio_write),
// ENTRY(PRAMIN, 0x700000, 0x100000, pramin_read, pramin_write),
ENTRY(USER, 0x800000, 0x800000, user_read, user_write),
ENTRY(PMC, pmc, 0x000000, 0x001000),
ENTRY(PBUS, pbus, 0x001000, 0x001000),
ENTRY(PFIFO, pfifo, 0x002000, 0x002000),
ENTRY(PRMA, prma, 0x007000, 0x001000),
ENTRY(PVIDEO, pvideo, 0x008000, 0x001000),
ENTRY(PTIMER, ptimer, 0x009000, 0x001000),
ENTRY(PCOUNTER, pcounter, 0x00a000, 0x001000),
ENTRY(PVPE, pvpe, 0x00b000, 0x001000),
ENTRY(PTV, ptv, 0x00d000, 0x001000),
ENTRY(PRMFB, prmfb, 0x0a0000, 0x020000),
ENTRY(PRMVIO, prmvio, 0x0c0000, 0x001000),
ENTRY(PFB, pfb, 0x100000, 0x001000),
ENTRY(PSTRAPS, pstraps, 0x101000, 0x001000),
ENTRY(PGRAPH, pgraph, 0x400000, 0x002000),
ENTRY(PCRTC, pcrtc, 0x600000, 0x001000),
ENTRY(PRMCIO, prmcio, 0x601000, 0x001000),
ENTRY(PRAMDAC, pramdac, 0x680000, 0x001000),
ENTRY(PRMDIO, prmdio, 0x681000, 0x001000),
// ENTRY(PRAMIN, pramin, 0x700000, 0x100000),
ENTRY(USER, user, 0x800000, 0x800000),
};
#undef ENTRY
#ifdef DEBUG_NV2A_REG
static const char *nv2a_reg_names[] = {};
void nv2a_reg_log_read(int block, hwaddr addr, uint64_t val)
{
if (blocktable[block].name) {
hwaddr naddr = blocktable[block].offset + addr;
if (naddr < ARRAY_SIZE(nv2a_reg_names) && nv2a_reg_names[naddr]) {
NV2A_DPRINTF("%s: read [%s] -> 0x%" PRIx64 "\n",
blocktable[block].name, nv2a_reg_names[naddr], val);
} else {
NV2A_DPRINTF("%s: read [%" HWADDR_PRIx "] -> 0x%" PRIx64 "\n",
blocktable[block].name, addr, val);
}
} else {
NV2A_DPRINTF("(%d?): read [%" HWADDR_PRIx "] -> 0x%" PRIx64 "\n",
block, addr, val);
}
}
void nv2a_reg_log_write(int block, hwaddr addr, uint64_t val)
{
if (blocktable[block].name) {
hwaddr naddr = blocktable[block].offset + addr;
if (naddr < ARRAY_SIZE(nv2a_reg_names) && nv2a_reg_names[naddr]) {
NV2A_DPRINTF("%s: [%s] = 0x%" PRIx64 "\n",
blocktable[block].name, nv2a_reg_names[naddr], val);
} else {
NV2A_DPRINTF("%s: [%" HWADDR_PRIx "] = 0x%" PRIx64 "\n",
blocktable[block].name, addr, val);
}
} else {
NV2A_DPRINTF("(%d?): [%" HWADDR_PRIx "] = 0x%" PRIx64 "\n",
block, addr, val);
}
}
#endif
static int nv2a_get_bpp(VGACommonState *s)
{
NV2AState *d = container_of(s, NV2AState, vga);

View File

@ -41,6 +41,7 @@
#include "hw/pci/pci.h"
#include "cpu.h"
#include "trace.h"
#include "swizzle.h"
#include "lru.h"
#include "gl/gloffscreen.h"
@ -488,19 +489,32 @@ typedef struct NV2ABlockInfo {
uint64_t size;
MemoryRegionOps ops;
} NV2ABlockInfo;
extern const NV2ABlockInfo blocktable[NV_NUM_BLOCKS];
extern GloContext *g_nv2a_context_render;
extern GloContext *g_nv2a_context_display;
void nv2a_update_irq(NV2AState *d);
#ifdef DEBUG_NV2A_REG
void nv2a_reg_log_read(int block, hwaddr addr, uint64_t val);
void nv2a_reg_log_write(int block, hwaddr addr, uint64_t val);
#else
#define nv2a_reg_log_read(block, addr, val) do {} while (0)
#define nv2a_reg_log_write(block, addr, val) do {} while (0)
#endif
static inline
void nv2a_reg_log_read(int block, hwaddr addr, unsigned int size, uint64_t val)
{
const char *block_name = "UNK";
if (block < ARRAY_SIZE(blocktable) && blocktable[block].name) {
block_name = blocktable[block].name;
}
trace_nv2a_reg_read(block_name, addr, size, val);
}
static inline
void nv2a_reg_log_write(int block, hwaddr addr, unsigned int size, uint64_t val)
{
const char *block_name = "UNK";
if (block < ARRAY_SIZE(blocktable) && blocktable[block].name) {
block_name = blocktable[block].name;
}
trace_nv2a_reg_write(block_name, addr, size, val);
}
#define DEFINE_PROTO(n) \
uint64_t n##_read(void *opaque, hwaddr addr, unsigned int size); \

View File

@ -42,7 +42,7 @@ uint64_t pbus_read(void *opaque, hwaddr addr, unsigned int size)
break;
}
nv2a_reg_log_read(NV_PBUS, addr, r);
nv2a_reg_log_read(NV_PBUS, addr, size, r);
return r;
}
@ -51,7 +51,7 @@ void pbus_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
NV2AState *s = opaque;
PCIDevice *d = PCI_DEVICE(s);
nv2a_reg_log_write(NV_PBUS, addr, val);
nv2a_reg_log_write(NV_PBUS, addr, size, val);
switch (addr) {
case NV_PBUS_PCI_NV_1:

View File

@ -43,7 +43,7 @@ uint64_t pcrtc_read(void *opaque, hwaddr addr, unsigned int size)
break;
}
nv2a_reg_log_read(NV_PCRTC, addr, r);
nv2a_reg_log_read(NV_PCRTC, addr, size, r);
return r;
}
@ -51,7 +51,7 @@ void pcrtc_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
{
NV2AState *d = (NV2AState *)opaque;
nv2a_reg_log_write(NV_PCRTC, addr, val);
nv2a_reg_log_write(NV_PCRTC, addr, size, val);
switch (addr) {
case NV_PCRTC_INTR_0:

View File

@ -42,7 +42,7 @@ uint64_t pfb_read(void *opaque, hwaddr addr, unsigned int size)
break;
}
nv2a_reg_log_read(NV_PFB, addr, r);
nv2a_reg_log_read(NV_PFB, addr, size, r);
return r;
}
@ -50,7 +50,7 @@ void pfb_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
{
NV2AState *d = (NV2AState *)opaque;
nv2a_reg_log_write(NV_PFB, addr, val);
nv2a_reg_log_write(NV_PFB, addr, size, val);
switch (addr) {
default:

View File

@ -58,7 +58,7 @@ uint64_t pfifo_read(void *opaque, hwaddr addr, unsigned int size)
qemu_mutex_unlock(&d->pfifo.lock);
nv2a_reg_log_read(NV_PFIFO, addr, r);
nv2a_reg_log_read(NV_PFIFO, addr, size, r);
return r;
}
@ -66,7 +66,7 @@ void pfifo_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
{
NV2AState *d = (NV2AState *)opaque;
nv2a_reg_log_write(NV_PFIFO, addr, val);
nv2a_reg_log_write(NV_PFIFO, addr, size, val);
qemu_mutex_lock(&d->pfifo.lock);

View File

@ -20,6 +20,7 @@
*/
#include "nv2a_int.h"
#include "s3tc.h"
#include "ui/xemu-settings.h"
#include "qemu/fast-hash.h"
@ -511,7 +512,7 @@ uint64_t pgraph_read(void *opaque, hwaddr addr, unsigned int size)
qemu_mutex_unlock(&pg->lock);
nv2a_reg_log_read(NV_PGRAPH, addr, r);
nv2a_reg_log_read(NV_PGRAPH, addr, size, r);
return r;
}
@ -520,7 +521,7 @@ void pgraph_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
NV2AState *d = (NV2AState *)opaque;
PGRAPHState *pg = &d->pgraph;
nv2a_reg_log_write(NV_PGRAPH, addr, val);
nv2a_reg_log_write(NV_PGRAPH, addr, size, val);
qemu_mutex_lock(&d->pfifo.lock); // FIXME: Factor out fifo lock here
qemu_mutex_lock(&pg->lock);
@ -1006,7 +1007,6 @@ int pgraph_method(NV2AState *d, unsigned int subchannel,
uint32_t graphics_class = GET_MASK(pg->regs[NV_PGRAPH_CTX_SWITCH1],
NV_PGRAPH_CTX_SWITCH1_GRCLASS);
// NV2A_DPRINTF("graphics_class %d 0x%x\n", subchannel, graphics_class);
pgraph_method_log(subchannel, graphics_class, method, parameter);
if (subchannel != 0) {
@ -1016,128 +1016,140 @@ int pgraph_method(NV2AState *d, unsigned int subchannel,
/* ugly switch for now */
switch (graphics_class) {
case NV_BETA: { switch (method) {
case NV012_SET_OBJECT:
beta->object_instance = parameter;
break;
case NV012_SET_BETA:
if (parameter & 0x80000000) {
beta->beta = 0;
} else {
// The parameter is a signed fixed-point number with a sign bit and
// 31 fractional bits. Note that negative values are clamped to 0,
// and only 8 fractional bits are actually implemented in hardware.
beta->beta = parameter & 0x7f800000;
case NV_BETA: {
switch (method) {
case NV012_SET_OBJECT:
beta->object_instance = parameter;
break;
case NV012_SET_BETA:
if (parameter & 0x80000000) {
beta->beta = 0;
} else {
// The parameter is a signed fixed-point number with a sign bit
// and 31 fractional bits. Note that negative values are clamped
// to 0, and only 8 fractional bits are actually implemented in
// hardware.
beta->beta = parameter & 0x7f800000;
}
break;
default:
goto unhandled;
}
break;
} break; }
case NV_CONTEXT_PATTERN: { switch (method) {
case NV044_SET_MONOCHROME_COLOR0:
pg->regs[NV_PGRAPH_PATT_COLOR0] = parameter;
break;
} break; }
case NV_CONTEXT_SURFACES_2D: { switch (method) {
case NV062_SET_OBJECT:
context_surfaces_2d->object_instance = parameter;
break;
case NV062_SET_CONTEXT_DMA_IMAGE_SOURCE:
context_surfaces_2d->dma_image_source = parameter;
break;
case NV062_SET_CONTEXT_DMA_IMAGE_DESTIN:
context_surfaces_2d->dma_image_dest = parameter;
break;
case NV062_SET_COLOR_FORMAT:
context_surfaces_2d->color_format = parameter;
break;
case NV062_SET_PITCH:
context_surfaces_2d->source_pitch = parameter & 0xFFFF;
context_surfaces_2d->dest_pitch = parameter >> 16;
break;
case NV062_SET_OFFSET_SOURCE:
context_surfaces_2d->source_offset = parameter & 0x07FFFFFF;
break;
case NV062_SET_OFFSET_DESTIN:
context_surfaces_2d->dest_offset = parameter & 0x07FFFFFF;
break;
} break; }
case NV_IMAGE_BLIT: { switch (method) {
case NV09F_SET_OBJECT:
image_blit->object_instance = parameter;
break;
case NV09F_SET_CONTEXT_SURFACES:
image_blit->context_surfaces = parameter;
break;
case NV09F_SET_OPERATION:
image_blit->operation = parameter;
break;
case NV09F_CONTROL_POINT_IN:
image_blit->in_x = parameter & 0xFFFF;
image_blit->in_y = parameter >> 16;
break;
case NV09F_CONTROL_POINT_OUT:
image_blit->out_x = parameter & 0xFFFF;
image_blit->out_y = parameter >> 16;
break;
case NV09F_SIZE:
image_blit->width = parameter & 0xFFFF;
image_blit->height = parameter >> 16;
if (image_blit->width && image_blit->height) {
pgraph_image_blit(d);
}
case NV_CONTEXT_PATTERN: {
switch (method) {
case NV044_SET_MONOCHROME_COLOR0:
pg->regs[NV_PGRAPH_PATT_COLOR0] = parameter;
break;
default:
goto unhandled;
}
break;
} break; }
}
case NV_CONTEXT_SURFACES_2D: {
switch (method) {
case NV062_SET_OBJECT:
context_surfaces_2d->object_instance = parameter;
break;
case NV062_SET_CONTEXT_DMA_IMAGE_SOURCE:
context_surfaces_2d->dma_image_source = parameter;
break;
case NV062_SET_CONTEXT_DMA_IMAGE_DESTIN:
context_surfaces_2d->dma_image_dest = parameter;
break;
case NV062_SET_COLOR_FORMAT:
context_surfaces_2d->color_format = parameter;
break;
case NV062_SET_PITCH:
context_surfaces_2d->source_pitch = parameter & 0xFFFF;
context_surfaces_2d->dest_pitch = parameter >> 16;
break;
case NV062_SET_OFFSET_SOURCE:
context_surfaces_2d->source_offset = parameter & 0x07FFFFFF;
break;
case NV062_SET_OFFSET_DESTIN:
context_surfaces_2d->dest_offset = parameter & 0x07FFFFFF;
break;
default:
goto unhandled;
}
break;
}
case NV_IMAGE_BLIT: {
switch (method) {
case NV09F_SET_OBJECT:
image_blit->object_instance = parameter;
break;
case NV09F_SET_CONTEXT_SURFACES:
image_blit->context_surfaces = parameter;
break;
case NV09F_SET_OPERATION:
image_blit->operation = parameter;
break;
case NV09F_CONTROL_POINT_IN:
image_blit->in_x = parameter & 0xFFFF;
image_blit->in_y = parameter >> 16;
break;
case NV09F_CONTROL_POINT_OUT:
image_blit->out_x = parameter & 0xFFFF;
image_blit->out_y = parameter >> 16;
break;
case NV09F_SIZE:
image_blit->width = parameter & 0xFFFF;
image_blit->height = parameter >> 16;
if (image_blit->width && image_blit->height) {
pgraph_image_blit(d);
}
break;
default:
goto unhandled;
}
break;
}
case NV_KELVIN_PRIMITIVE: {
MethodFunc handler =
pgraph_kelvin_methods[METHOD_ADDR_TO_INDEX(method)].handler;
if (handler == NULL) {
NV2A_GL_DPRINTF(true, " unhandled (0x%02x 0x%08x)",
graphics_class, method);
} else {
size_t num_words_consumed = 1;
handler(d, pg, subchannel, method, parameter, parameters,
num_words_available, &num_words_consumed, inc);
/* Squash repeated BEGIN,DRAW_ARRAYS,END */
#define LAM(i, mthd) ((parameters[i*2+1] & 0x31fff) == (mthd))
#define LAP(i, prm) (parameters[i*2+2] == (prm))
#define LAMP(i, mthd, prm) (LAM(i, mthd) && LAP(i, prm))
if (method == NV097_DRAW_ARRAYS && (max_lookahead_words >= 7) &&
pg->draw_arrays_length <
(ARRAY_SIZE(pg->gl_draw_arrays_start) - 1) &&
LAMP(0, NV097_SET_BEGIN_END, NV097_SET_BEGIN_END_OP_END) &&
LAMP(1, NV097_SET_BEGIN_END, pg->primitive_mode) &&
LAM(2, NV097_DRAW_ARRAYS)) {
num_words_consumed += 4;
pg->draw_arrays_prevent_connect = true;
}
#undef LAM
#undef LAP
#undef LAMP
num_processed = num_words_consumed;
goto unhandled;
}
size_t num_words_consumed = 1;
handler(d, pg, subchannel, method, parameter, parameters,
num_words_available, &num_words_consumed, inc);
/* Squash repeated BEGIN,DRAW_ARRAYS,END */
#define LAM(i, mthd) ((parameters[i*2+1] & 0x31fff) == (mthd))
#define LAP(i, prm) (parameters[i*2+2] == (prm))
#define LAMP(i, mthd, prm) (LAM(i, mthd) && LAP(i, prm))
if (method == NV097_DRAW_ARRAYS && (max_lookahead_words >= 7) &&
pg->draw_arrays_length <
(ARRAY_SIZE(pg->gl_draw_arrays_start) - 1) &&
LAMP(0, NV097_SET_BEGIN_END, NV097_SET_BEGIN_END_OP_END) &&
LAMP(1, NV097_SET_BEGIN_END, pg->primitive_mode) &&
LAM(2, NV097_DRAW_ARRAYS)) {
num_words_consumed += 4;
pg->draw_arrays_prevent_connect = true;
}
#undef LAM
#undef LAP
#undef LAMP
num_processed = num_words_consumed;
break;
}
default:
NV2A_GL_DPRINTF(true, " unhandled (0x%02x 0x%08x)",
graphics_class, method);
break;
goto unhandled;
}
return num_processed;
unhandled:
trace_nv2a_pgraph_method_unhandled(subchannel, graphics_class,
method, parameter);
return num_processed;
}
DEF_METHOD(NV097, SET_OBJECT)
@ -1206,25 +1218,27 @@ DEF_METHOD(NV097, SET_FLIP_MODULO)
DEF_METHOD(NV097, FLIP_INCREMENT_WRITE)
{
NV2A_DPRINTF("flip increment write %d -> ",
GET_MASK(pg->regs[NV_PGRAPH_SURFACE],
NV_PGRAPH_SURFACE_WRITE_3D));
uint32_t old =
GET_MASK(pg->regs[NV_PGRAPH_SURFACE], NV_PGRAPH_SURFACE_WRITE_3D);
SET_MASK(pg->regs[NV_PGRAPH_SURFACE],
NV_PGRAPH_SURFACE_WRITE_3D,
(GET_MASK(pg->regs[NV_PGRAPH_SURFACE],
NV_PGRAPH_SURFACE_WRITE_3D)+1)
% GET_MASK(pg->regs[NV_PGRAPH_SURFACE],
NV_PGRAPH_SURFACE_MODULO_3D) );
NV2A_DPRINTF("%d\n",
GET_MASK(pg->regs[NV_PGRAPH_SURFACE],
NV_PGRAPH_SURFACE_WRITE_3D));
uint32_t new =
GET_MASK(pg->regs[NV_PGRAPH_SURFACE], NV_PGRAPH_SURFACE_WRITE_3D);
trace_nv2a_pgraph_flip_increment_write(old, new);
NV2A_GL_DFRAME_TERMINATOR();
pg->frame_time++;
}
DEF_METHOD(NV097, FLIP_STALL)
{
trace_nv2a_pgraph_flip_stall();
pgraph_update_surface(d, false, true, true);
nv2a_profile_flip_stall();
pg->waiting_for_flip = true;
@ -3392,7 +3406,6 @@ DEF_METHOD(NV097, SET_TRANSFORM_CONSTANT_LOAD)
assert(parameter < NV2A_VERTEXSHADER_CONSTANTS);
SET_MASK(pg->regs[NV_PGRAPH_CHEOPS_OFFSET],
NV_PGRAPH_CHEOPS_OFFSET_CONST_LD_PTR, parameter);
NV2A_DPRINTF("load to %d\n", parameter);
}
@ -3425,60 +3438,52 @@ void pgraph_context_switch(NV2AState *d, unsigned int channel_id)
static void pgraph_method_log(unsigned int subchannel,
unsigned int graphics_class,
unsigned int method, uint32_t parameter) {
#ifdef DEBUG_NV2A
unsigned int method, uint32_t parameter)
{
const char *method_name = "?";
static unsigned int last = 0;
static unsigned int count = 0;
if (last == 0x1800 && method != last) {
NV2A_GL_DPRINTF(true, "pgraph method (%d) 0x%x * %d",
subchannel, last, count);
if (last == NV097_ARRAY_ELEMENT16 && method != last) {
method_name = "NV097_ARRAY_ELEMENT16";
trace_nv2a_pgraph_method_abbrev(subchannel, graphics_class, last,
method_name, count);
NV2A_GL_DPRINTF(false, "pgraph method (%d) 0x%x %s * %d", subchannel,
last, method_name, count);
}
if (method != 0x1800) {
const char* method_name = NULL;
if (method != NV097_ARRAY_ELEMENT16) {
uint32_t base = method;
// unsigned int nmethod = 0;
switch (graphics_class) {
case NV_KELVIN_PRIMITIVE: {
// nmethod = method | (0x5c << 16);
int idx = METHOD_ADDR_TO_INDEX(method);
if (idx < ARRAY_SIZE(pgraph_kelvin_methods)) {
method_name = pgraph_kelvin_methods[idx].name;
base = pgraph_kelvin_methods[idx].base;
}
break;
case NV_KELVIN_PRIMITIVE: {
int idx = METHOD_ADDR_TO_INDEX(method);
if (idx < ARRAY_SIZE(pgraph_kelvin_methods) &&
pgraph_kelvin_methods[idx].handler) {
method_name = pgraph_kelvin_methods[idx].name;
base = pgraph_kelvin_methods[idx].base;
}
case NV_CONTEXT_SURFACES_2D:
// nmethod = method | (0x6d << 16);
break;
case NV_CONTEXT_PATTERN:
// nmethod = method | (0x68 << 16);
break;
default:
break;
break;
}
default:
break;
}
char buf[256];
char *ptr = buf;
char *end = ptr + sizeof(buf);
ptr += snprintf(ptr, end - ptr, "pgraph method (%d): 0x%x -> 0x%04x",
subchannel, graphics_class, method);
if (method_name) {
ptr += snprintf(ptr, end - ptr, " %s", method_name);
uint32_t o = method - base;
if (o) {
ptr += snprintf(ptr, end - ptr, "+0x%02x", o);
}
}
ptr += snprintf(ptr, end - ptr, " (0x%x)", parameter);
NV2A_GL_DPRINTF(true, "%s", buf);
uint32_t offset = method - base;
trace_nv2a_pgraph_method(subchannel, graphics_class, method,
method_name, offset, parameter);
NV2A_GL_DPRINTF(false,
"pgraph method (%d): 0x%" PRIx32 " -> 0x%04" PRIx32
" %s[%" PRId32 "] 0x%" PRIx32,
subchannel, graphics_class, method, method_name, offset,
parameter);
}
if (method == last) {
count++;
} else {
count = 0;
}
if (method == last) { count++; }
else {count = 0; }
last = method;
#endif
}
static void pgraph_allocate_inline_buffer_vertices(PGRAPHState *pg,
@ -4954,16 +4959,12 @@ static void pgraph_surface_access_callback(
assert(offset < e->size);
if (qatomic_read(&e->draw_dirty)) {
NV2A_XPRINTF(DBG_SURFACE_SYNC,
"Surface accessed at %" HWADDR_PRIx "+%" HWADDR_PRIx "\n",
e->vram_addr, offset);
trace_nv2a_pgraph_surface_cpu_access(e->vram_addr, offset);
pgraph_wait_for_surface_download(e);
}
if (write && !qatomic_read(&e->upload_pending)) {
NV2A_XPRINTF(DBG_SURFACE_SYNC,
"Surface write at %" HWADDR_PRIx "+%" HWADDR_PRIx "\n",
e->vram_addr, offset);
trace_nv2a_pgraph_surface_cpu_access(e->vram_addr, offset);
qatomic_set(&e->upload_pending, true);
}
}
@ -4973,9 +4974,8 @@ static SurfaceBinding *pgraph_surface_put(NV2AState *d,
SurfaceBinding *surface_in)
{
assert(pgraph_surface_get(d, addr) == NULL);
NV2A_XPRINTF(DBG_SURFACES,
"Adding surface region at [%" HWADDR_PRIx ": %" HWADDR_PRIx ")\n",
surface_in->vram_addr, surface_in->vram_addr + surface_in->size);
trace_nv2a_pgraph_surface_created(surface_in->vram_addr,
surface_in->vram_addr + surface_in->size);
SurfaceBinding *surface, *next;
uintptr_t e_end = surface_in->vram_addr + surface_in->size - 1;
@ -5039,8 +5039,7 @@ static SurfaceBinding *pgraph_surface_get_within(NV2AState *d, hwaddr addr)
static void pgraph_surface_invalidate(NV2AState *d, SurfaceBinding *surface)
{
NV2A_XPRINTF(DBG_SURFACES, "Removing surface at %" HWADDR_PRIx "\n",
surface->vram_addr);
trace_nv2a_pgraph_surface_invalidated(surface->vram_addr);
assert(surface != d->pgraph.color_binding);
assert(surface != d->pgraph.zeta_binding);

View File

@ -46,7 +46,7 @@ uint64_t pmc_read(void *opaque, hwaddr addr, unsigned int size)
break;
}
nv2a_reg_log_read(NV_PMC, addr, r);
nv2a_reg_log_read(NV_PMC, addr, size, r);
return r;
}
@ -54,7 +54,7 @@ void pmc_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
{
NV2AState *d = (NV2AState *)opaque;
nv2a_reg_log_write(NV_PMC, addr, val);
nv2a_reg_log_write(NV_PMC, addr, size, val);
switch (addr) {
case NV_PMC_INTR_0:

View File

@ -74,8 +74,7 @@ uint64_t pramdac_read(void *opaque, hwaddr addr, unsigned int size)
/* Surprisingly, QEMU doesn't handle unaligned access for you properly */
r >>= 32 - 8 * size - 8 * (addr & 3);
NV2A_DPRINTF("PRAMDAC: read %d [0x%" HWADDR_PRIx "] -> %" PRIx64 "\n", size,
addr, r);
nv2a_reg_log_read(NV_PRAMDAC, addr, size, r);
return r;
}
@ -84,7 +83,7 @@ void pramdac_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
NV2AState *d = (NV2AState *)opaque;
uint32_t m, n, p;
nv2a_reg_log_write(NV_PRAMDAC, addr, val);
nv2a_reg_log_write(NV_PRAMDAC, addr, size, val);
switch (addr) {
case NV_PRAMDAC_NVPLL_COEFF:

View File

@ -27,7 +27,7 @@ uint64_t prmcio_read(void *opaque, hwaddr addr, unsigned int size)
NV2AState *d = opaque;
uint64_t r = vga_ioport_read(&d->vga, addr);
nv2a_reg_log_read(NV_PRMCIO, addr, r);
nv2a_reg_log_read(NV_PRMCIO, addr, size, r);
return r;
}
@ -35,7 +35,7 @@ void prmcio_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
{
NV2AState *d = opaque;
nv2a_reg_log_write(NV_PRMCIO, addr, val);
nv2a_reg_log_write(NV_PRMCIO, addr, size, val);
switch (addr) {
case VGA_ATT_W:

View File

@ -32,7 +32,7 @@ uint64_t prmdio_read(void *opaque, hwaddr addr, unsigned int size)
break;
}
nv2a_reg_log_read(NV_PRMDIO, addr, r);
nv2a_reg_log_read(NV_PRMDIO, addr, size, r);
return r;
}
@ -40,7 +40,7 @@ void prmdio_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
{
NV2AState *d = (NV2AState *)opaque;
nv2a_reg_log_write(NV_PRMDIO, addr, val);
nv2a_reg_log_write(NV_PRMDIO, addr, size, val);
switch (addr) {
case NV_USER_DAC_WRITE_MODE_ADDRESS:

View File

@ -27,7 +27,7 @@ uint64_t prmvio_read(void *opaque, hwaddr addr, unsigned int size)
NV2AState *d = opaque;
uint64_t r = vga_ioport_read(&d->vga, addr);
nv2a_reg_log_read(NV_PRMVIO, addr, r);
nv2a_reg_log_read(NV_PRMVIO, addr, size, r);
return r;
}
@ -35,6 +35,6 @@ void prmvio_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
{
NV2AState *d = opaque;
nv2a_reg_log_write(NV_PRMVIO, addr, val);
nv2a_reg_log_write(NV_PRMVIO, addr, size, val);
vga_ioport_write(&d->vga, addr, val);
}

View File

@ -59,7 +59,7 @@ uint64_t ptimer_read(void *opaque, hwaddr addr, unsigned int size)
break;
}
nv2a_reg_log_read(NV_PTIMER, addr, r);
nv2a_reg_log_read(NV_PTIMER, addr, size, r);
return r;
}
@ -67,7 +67,7 @@ void ptimer_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
{
NV2AState *d = opaque;
nv2a_reg_log_write(NV_PTIMER, addr, val);
nv2a_reg_log_write(NV_PTIMER, addr, size, val);
switch (addr) {
case NV_PTIMER_INTR_0:

View File

@ -45,7 +45,7 @@ uint64_t pvideo_read(void *opaque, hwaddr addr, unsigned int size)
break;
}
nv2a_reg_log_read(NV_PVIDEO, addr, r);
nv2a_reg_log_read(NV_PVIDEO, addr, size, r);
return r;
}
@ -53,7 +53,7 @@ void pvideo_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
{
NV2AState *d = opaque;
nv2a_reg_log_write(NV_PVIDEO, addr, val);
nv2a_reg_log_write(NV_PVIDEO, addr, size, val);
switch (addr) {
case NV_PVIDEO_BUFFER:

View File

@ -26,7 +26,7 @@
hwaddr addr, \
unsigned int size) \
{ \
nv2a_reg_log_read(region_id, addr, 0); \
nv2a_reg_log_read(region_id, addr, size, 0); \
return 0; \
} \
void name ## _write(void *opaque, \
@ -34,7 +34,7 @@
uint64_t val, \
unsigned int size) \
{ \
nv2a_reg_log_write(region_id, addr, val); \
nv2a_reg_log_write(region_id, addr, size, val); \
} \
DEFINE_STUB(prma, NV_PRMA)

17
hw/xbox/nv2a/trace-events Normal file
View File

@ -0,0 +1,17 @@
# See docs/devel/tracing.rst for syntax documentation.
# nv2a.c
nv2a_reg_read(const char *block, uint32_t addr, unsigned int size, uint64_t val) "%s addr 0x%"PRIx32" size %d val 0x%"PRIx64
nv2a_reg_write(const char *block, uint32_t addr, unsigned int size, uint64_t val) "%s addr 0x%"PRIx32" size %d val 0x%"PRIx64
nv2a_irq(uint32_t pending) "%08"PRIx32
nv2a_dma_map(uint32_t obj_address, uint32_t dma_class, uint32_t dma_target, uint32_t dma_addr, uint32_t dma_limit) "obj 0x%08"PRIx32" class 0x%08"PRIx32" target 0x%08"PRIx32" addr 0x%08"PRIx32" limit 0x%08"PRIx32
# pgraph.c
nv2a_pgraph_method(uint32_t subchannel, uint32_t graphics_class, uint32_t method, const char *name, uint32_t offset, uint32_t parameter) "%d: 0x%"PRIx32" -> 0x%04"PRIx32" %s[%"PRId32"] 0x%"PRIx32
nv2a_pgraph_method_abbrev(uint32_t subchannel, uint32_t graphics_class, uint32_t method, const char *name, unsigned int count) "%d: 0x%"PRIx32" -> 0x%04"PRIx32" %s * %d"
nv2a_pgraph_method_unhandled(uint32_t subchannel, uint32_t graphics_class, uint32_t method, uint32_t parameter) "%d: 0x%"PRIx32" -> 0x%04"PRIx32" 0x%"PRIx32
nv2a_pgraph_surface_cpu_access(uint32_t addr, uint32_t offset) "0x%08"PRIx32"+0x%"PRIx32
nv2a_pgraph_surface_created(uint32_t addr, uint32_t end_addr) "[0x%08"PRIx32", 0x%08"PRIx32")"
nv2a_pgraph_surface_invalidated(uint32_t addr) "0x%08"PRIx32
nv2a_pgraph_flip_stall(void) ""
nv2a_pgraph_flip_increment_write(uint32_t write3d_old, uint32_t write3d_new) "0x%"PRIx32" -> 0x%"PRIx32

1
hw/xbox/nv2a/trace.h Normal file
View File

@ -0,0 +1 @@
#include "trace/trace-hw_xbox_nv2a.h"

View File

@ -66,7 +66,7 @@ uint64_t user_read(void *opaque, hwaddr addr, unsigned int size)
qemu_mutex_unlock(&d->pfifo.lock);
nv2a_reg_log_read(NV_USER, addr, r);
nv2a_reg_log_read(NV_USER, addr, size, r);
return r;
}
@ -74,7 +74,7 @@ void user_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size)
{
NV2AState *d = (NV2AState *)opaque;
nv2a_reg_log_write(NV_USER, addr, val);
nv2a_reg_log_write(NV_USER, addr, size, val);
unsigned int channel_id = addr >> 16;
assert(channel_id < NV2A_NUM_CHANNELS);

View File

@ -2186,6 +2186,7 @@ if have_system
'softmmu',
'ui',
'hw/remote',
'hw/xbox/nv2a',
]
endif
if have_system or have_user