Difference between revisions of "BAR Emulation Specification"
(Remove unpaired blockquote tags left by reference cleanup) |
m (Re-sync page from tracked wiki source: fix cross-document links and diagram; refresh status) |
||
| Line 1: | Line 1: | ||
= BAR Emulation Specification (GSP 570.144W) = | = BAR Emulation Specification (GSP 570.144W) = | ||
< | <blockquote>'''Historical document — superseded.''' The <code>BAR_TRAP</code> RPC (type 0x0A) described here is '''not used''': in emulation mode it returns <code>-ENOTSUPP</code>, and BAR access is synchronous MMIO through the BAR shadow. Guest-visible BAR windows are BAR0 (16 MB register MMIO), BAR1 (256 MB VRAM aperture) and BAR3 (instance window). Canonical documentation: [https://git.vgpu.io/open-iov/blob/master/docs/03-architecture/06-host-module-and-hybrid-model.md <code>../docs/03-architecture/06-host-module-and-hybrid-model.md</code>].</blockquote> | ||
== Overview == | == Overview == | ||
< | The GSP firmware implements BAR (Base Address Register) emulation for virtual GPU (vGPU) through the '''BAR_TRAP''' RPC (type 0x0A). The main handler at '''0x04CB8188''' (40 KB) manages BAR1 aperture, forced access, and memory backing. '''This RPC is not used by the live path''': in emulation mode <code>BAR_TRAP</code> returns <code>-ENOTSUPP</code>; guest BAR access is handled synchronously as MMIO through the BAR shadow (<code>../kernel/bar_emulation.c</code>), not via an RPC. | ||
== Key Addresses == | == Key Addresses == | ||
| Line 47: | Line 48: | ||
|} | |} | ||
== Handler State Machine == | == Handler State Machine == | ||
=== Main Loop (0x04CB8188) === | === Main Loop (0x04CB8188) === | ||
The handler runs a continuous event loop processing BAR trap requests: | The handler runs a continuous event loop processing BAR trap requests: | ||
< | <pre>while (true) { | ||
// Wait for trap event (bitmask in unaff_s5) | // Wait for trap event (bitmask in unaff_s5) | ||
event = wait_for_bar_event; | event = wait_for_bar_event(); | ||
switch (event & 0x3F) { | switch (event & 0x3F) { | ||
case 0x01: // BAR1 write access | case 0x01: // BAR1 write access | ||
handle_bar1_write; | handle_bar1_write(); | ||
break; | break; | ||
case 0x02: // BAR1 read access | case 0x02: // BAR1 read access | ||
handle_bar1_read; | handle_bar1_read(); | ||
break; | break; | ||
case 0x08: // Aperture configuration | case 0x08: // Aperture configuration | ||
handle_aperture_config; | handle_aperture_config(); | ||
break; | break; | ||
case 0x10: // ForceBarAccess | case 0x10: // ForceBarAccess | ||
handle_force_access; | handle_force_access(); | ||
break; | break; | ||
case 0x20: // Bar1Rest (restore) | case 0x20: // Bar1Rest (restore) | ||
handle_bar1_restore; | handle_bar1_restore(); | ||
break; | break; | ||
default: | default: | ||
return ERROR_UNKNOWN_EVENT; | return ERROR_UNKNOWN_EVENT; | ||
} | } | ||
}</ | }</pre> | ||
=== Event Bitmask === | === Event Bitmask === | ||
| Line 109: | Line 108: | ||
|} | |} | ||
== Memory Management == | == Memory Management == | ||
=== Allocator Arena (0x429B450) === | === Allocator Arena (0x429B450) === | ||
< | <pre>// Allocate backing store for BAR emulation | ||
void *bar_alloc(size_t size) { | void *bar_alloc(size_t size) { | ||
// Calls UNK_ram_058A1A9C(0x429B450, size) | // Calls UNK_ram_058A1A9C(0x429B450, size) | ||
| Line 124: | Line 121: | ||
void bar_free(void *ptr) { | void bar_free(void *ptr) { | ||
// Calls UNK_ram_05895BF4(0x429B428, ptr) | // Calls UNK_ram_05895BF4(0x429B428, ptr) | ||
}</ | }</pre> | ||
=== Allocation Sizes === | === Allocation Sizes === | ||
| Line 132: | Line 129: | ||
* '''Force access buffer''': 0x1000 (4 KB) | * '''Force access buffer''': 0x1000 (4 KB) | ||
=== Cache Coherency === | === Cache Coherency === | ||
< | <pre>// Flush cache for DMA | ||
void bar_cache_flush(void *addr, size_t size) { | void bar_cache_flush(void *addr, size_t size) { | ||
UNK_ram_05895BF4(0x429B428, addr); | UNK_ram_05895BF4(0x429B428, addr); | ||
UNK_ram_05895BF4(0x429B428, addr + size); | UNK_ram_05895BF4(0x429B428, addr + size); | ||
}</ | }</pre> | ||
== BAR1 Emulation Logic == | == BAR1 Emulation Logic == | ||
=== Write Path (Event 0x01) === | === Write Path (Event 0x01) === | ||
< | <pre>int handle_bar1_write(bar_trap_t *trap) { | ||
// 1. Validate offset within aperture | // 1. Validate offset within aperture | ||
if (trap- | if (trap->offset >= bar1_aperture_size) | ||
return ERROR_OVERFLOW; | return ERROR_OVERFLOW; | ||
// 2. Check ForceBarAccess flag | // 2. Check ForceBarAccess flag | ||
if (force_bar_access && !(trap- | if (force_bar_access && !(trap->flags & FORCE_ALLOWED)) | ||
return ERROR_PERMISSION; | return ERROR_PERMISSION; | ||
// 3. Translate to backing store | // 3. Translate to backing store | ||
uint8_t *backing = bar1_backing + trap- | uint8_t *backing = bar1_backing + trap->offset; | ||
// 4. Perform write (1/2/4/8 bytes) | // 4. Perform write (1/2/4/8 bytes) | ||
switch (trap- | switch (trap->size) { | ||
case 1: *backing = trap- | case 1: *backing = trap->value; break; | ||
case 2: *(uint16_t*)backing = trap- | case 2: *(uint16_t*)backing = trap->value; break; | ||
case 4: *(uint32_t*)backing = trap- | case 4: *(uint32_t*)backing = trap->value; break; | ||
case 8: *(uint64_t*)backing = trap- | case 8: *(uint64_t*)backing = trap->value; break; | ||
} | } | ||
// 5. Flush to device if needed | // 5. Flush to device if needed | ||
if (device_needs_flush) | if (device_needs_flush) | ||
bar_cache_flush(backing, trap- | bar_cache_flush(backing, trap->size); | ||
return OK; | return OK; | ||
}</ | }</pre> | ||
=== Read Path (Event 0x02) === | === Read Path (Event 0x02) === | ||
< | <pre>int handle_bar1_read(bar_trap_t *trap) { | ||
if (trap- | if (trap->offset >= bar1_aperture_size) | ||
return ERROR_OVERFLOW; | return ERROR_OVERFLOW; | ||
uint8_t *backing = bar1_backing + trap- | uint8_t *backing = bar1_backing + trap->offset; | ||
switch (trap- | switch (trap->size) { | ||
case 1: *trap- | case 1: *trap->out_value = *backing; break; | ||
case 2: *trap- | case 2: *trap->out_value = *(uint16_t*)backing; break; | ||
case 4: *trap- | case 4: *trap->out_value = *(uint32_t*)backing; break; | ||
case 8: *trap- | case 8: *trap->out_value = *(uint64_t*)backing; break; | ||
} | } | ||
return OK; | return OK; | ||
}</ | }</pre> | ||
=== Aperture Configuration (Event 0x08) === | === Aperture Configuration (Event 0x08) === | ||
< | <pre>int handle_aperture_config(bar_config_t *cfg) { | ||
// Validate new aperture | // Validate new aperture | ||
if (cfg- | if (cfg->size > MAX_APERTURE_SIZE) // 0x40000 | ||
return ERROR_INVALID; | return ERROR_INVALID; | ||
if (cfg- | if (cfg->offset & 0xFFF) // Must be 4KB aligned | ||
return ERROR_ALIGNMENT; | return ERROR_ALIGNMENT; | ||
// Reallocate backing store if size changed | // Reallocate backing store if size changed | ||
if (cfg- | if (cfg->size != bar1_aperture_size) { | ||
void *new_backing = bar_alloc(cfg- | void *new_backing = bar_alloc(cfg->size); | ||
if (!new_backing) return ERROR_NOMEM; | if (!new_backing) return ERROR_NOMEM; | ||
// Copy existing data | // Copy existing data | ||
memcpy(new_backing, bar1_backing, | memcpy(new_backing, bar1_backing, | ||
min(cfg- | min(cfg->size, bar1_aperture_size)); | ||
bar_free(bar1_backing); | bar_free(bar1_backing); | ||
bar1_backing = new_backing; | bar1_backing = new_backing; | ||
bar1_aperture_size = cfg- | bar1_aperture_size = cfg->size; | ||
} | } | ||
bar1_aperture_offset = cfg- | bar1_aperture_offset = cfg->offset; | ||
return OK; | return OK; | ||
}</ | }</pre> | ||
=== ForceBarAccess (Event 0x10) === | === ForceBarAccess (Event 0x10) === | ||
< | <pre>int handle_force_access(force_access_t *fa) { | ||
// ForceBarAccess allows hypervisor to bypass VF permissions | // ForceBarAccess allows hypervisor to bypass VF permissions | ||
// Used for live migration, checkpoint/restore | // Used for live migration, checkpoint/restore | ||
force_bar_access = fa- | force_bar_access = fa->enable; | ||
force_access_vf = fa- | force_access_vf = fa->vf_id; | ||
force_access_range = fa- | force_access_range = fa->range; | ||
// Allocate shadow buffer for forced operations | // Allocate shadow buffer for forced operations | ||
if (fa- | if (fa->enable) { | ||
force_buffer = bar_alloc(0x1000); | force_buffer = bar_alloc(0x1000); | ||
if (!force_buffer) return ERROR_NOMEM; | if (!force_buffer) return ERROR_NOMEM; | ||
| Line 239: | Line 234: | ||
return OK; | return OK; | ||
}</ | }</pre> | ||
=== Bar1Rest - State Restore (Event 0x20) === | === Bar1Rest - State Restore (Event 0x20) === | ||
< | <pre>int handle_bar1_restore(restore_state_t *rs) { | ||
// Restore BAR1 state from checkpoint | // Restore BAR1 state from checkpoint | ||
// Used during VF live migration | // Used during VF live migration | ||
bar1_aperture_offset = rs- | bar1_aperture_offset = rs->aperture_offset; | ||
bar1_aperture_size = rs- | bar1_aperture_size = rs->aperture_size; | ||
force_bar_access = rs- | force_bar_access = rs->force_access; | ||
// Restore backing store from serialized data | // Restore backing store from serialized data | ||
if (rs- | if (rs->backing_size > 0) { | ||
void *new_backing = bar_alloc(rs- | void *new_backing = bar_alloc(rs->backing_size); | ||
if (!new_backing) return ERROR_NOMEM; | if (!new_backing) return ERROR_NOMEM; | ||
memcpy(new_backing, rs- | memcpy(new_backing, rs->backing_data, rs->backing_size); | ||
bar_free(bar1_backing); | bar_free(bar1_backing); | ||
bar1_backing = new_backing; | bar1_backing = new_backing; | ||
| Line 262: | Line 257: | ||
return OK; | return OK; | ||
}</ | }</pre> | ||
== vGPU-IO Integration == | == vGPU-IO Integration == | ||
=== Kernel BAR Trap Registration === | === Kernel BAR Trap Registration === | ||
< | <pre>struct gsp_bar_ops { | ||
int (*bar_trap)(struct gsp_device *gsp, | int (*bar_trap)(struct gsp_device *gsp, | ||
struct bar_trap_msg *msg); | struct bar_trap_msg *msg); | ||
| Line 283: | Line 277: | ||
}; | }; | ||
static const struct gsp_bar_ops gsp_bar_ops = {.bar_trap = gsp_bar_trap_handler,.configure_aperture = gsp_bar_config_aperture,.force_access = gsp_bar_force_access,.save_state = gsp_bar_save_state,.restore_state = gsp_bar_restore_state, | static const struct gsp_bar_ops gsp_bar_ops = { | ||
};</ | .bar_trap = gsp_bar_trap_handler, | ||
.configure_aperture = gsp_bar_config_aperture, | |||
.force_access = gsp_bar_force_access, | |||
.save_state = gsp_bar_save_state, | |||
.restore_state = gsp_bar_restore_state, | |||
};</pre> | |||
=== VF BAR Configuration === | === VF BAR Configuration === | ||
< | <pre>int gsp_vf_bar_init(struct gsp_vf *vf) { | ||
struct bar_config cfg = {.vf_id = vf- | struct bar_config cfg = { | ||
.vf_id = vf->id, | |||
.bar = 1, // BAR1 | |||
.aperture_offset = vf->bar1_offset, | |||
.aperture_size = vf->bar1_size, | |||
.flags = BAR_FLAG_COHERENT, | |||
}; | }; | ||
return gsp_rpc_send(vf- | return gsp_rpc_send(vf->gsp, RPC_BAR_TRAP, | ||
BAR_SUBCMD_CONFIG, &cfg, sizeof(cfg)); | BAR_SUBCMD_CONFIG, &cfg, sizeof(cfg)); | ||
}</ | }</pre> | ||
=== Live Migration Support === | === Live Migration Support === | ||
< | <pre>// Save BAR state for migration | ||
int gsp_vf_bar_save(struct gsp_vf *vf, void *buf, size_t *size) { | int gsp_vf_bar_save(struct gsp_vf *vf, void *buf, size_t *size) { | ||
struct bar_save_msg msg = {.vf_id = vf- | struct bar_save_msg msg = { | ||
.vf_id = vf->id, | |||
.bar = 1, | |||
}; | }; | ||
return gsp_rpc_send(vf- | return gsp_rpc_send(vf->gsp, RPC_BAR_TRAP, | ||
BAR_SUBCMD_SAVE, &msg, sizeof(msg), | BAR_SUBCMD_SAVE, &msg, sizeof(msg), | ||
buf, size); | buf, size); | ||
} | } | ||
| Line 310: | Line 316: | ||
// Restore BAR state on destination | // Restore BAR state on destination | ||
int gsp_vf_bar_restore(struct gsp_vf *vf, void *buf, size_t size) { | int gsp_vf_bar_restore(struct gsp_vf *vf, void *buf, size_t size) { | ||
struct bar_restore_msg msg = {.vf_id = vf- | struct bar_restore_msg msg = { | ||
.vf_id = vf->id, | |||
.bar = 1, | |||
.data = buf, | |||
.data_size = size, | |||
}; | }; | ||
return gsp_rpc_send(vf- | return gsp_rpc_send(vf->gsp, RPC_BAR_TRAP, | ||
BAR_SUBCMD_RESTORE, &msg, sizeof(msg)); | BAR_SUBCMD_RESTORE, &msg, sizeof(msg)); | ||
}</ | }</pre> | ||
== Error Handling == | == Error Handling == | ||
| Line 346: | Line 356: | ||
|} | |} | ||
== Debugging == | == Debugging == | ||
=== Key Registers to Monitor === | === Key Registers to Monitor === | ||
<pre>0x04296048: Global error flag (cRam0000000004296048) | <pre>0x04296048 : Global error flag (cRam0000000004296048) | ||
0x0429B750: Error status (0x111300 offset) | 0x0429B750 : Error status (0x111300 offset) | ||
0x429B428: Cache management base | 0x429B428 : Cache management base | ||
0x429B450: Allocator arena base</pre> | 0x429B450 : Allocator arena base</pre> | ||
=== Log Strings === | === Log Strings === | ||
| Line 367: | Line 375: | ||
* <code>Bar1Size</code> - Size queries | * <code>Bar1Size</code> - Size queries | ||
---- | |||
== Reference == | == Reference == | ||
Revision as of 04:09, 12 October 2026
BAR Emulation Specification (GSP 570.144W)
Historical document — superseded. The
BAR_TRAPRPC (type 0x0A) described here is not used: in emulation mode it returns-ENOTSUPP, and BAR access is synchronous MMIO through the BAR shadow. Guest-visible BAR windows are BAR0 (16 MB register MMIO), BAR1 (256 MB VRAM aperture) and BAR3 (instance window). Canonical documentation:../docs/03-architecture/06-host-module-and-hybrid-model.md.
Overview
The GSP firmware implements BAR (Base Address Register) emulation for virtual GPU (vGPU) through the BAR_TRAP RPC (type 0x0A). The main handler at 0x04CB8188 (40 KB) manages BAR1 aperture, forced access, and memory backing. This RPC is not used by the live path: in emulation mode BAR_TRAP returns -ENOTSUPP; guest BAR access is handled synchronously as MMIO through the BAR shadow (../kernel/bar_emulation.c), not via an RPC.
Key Addresses
| Component | Address | Description |
|---|---|---|
| BAR Trap Handler | 0x04CB8188 | Main emulation logic (40 KB) |
| RPC Jump Table Entry | 0x057675B7 | BAR_TRAP in secondary dispatcher |
| String: BAR1 | 0x0406570E, 0x04085DE0 | BAR1 identifier |
| String: Bar1Rest | 0x040656DA | BAR1 restore state |
| String: ForceBarAccess | 0x040656F2 | Forced access control |
| String: Bar1Aperture | 0x04065722 | Aperture configuration |
| Memory Allocator | 0x429B450 | Arena for BAR backing store |
| Cache Management | 0x429B428 | Flush/invalidate |
Handler State Machine
Main Loop (0x04CB8188)
The handler runs a continuous event loop processing BAR trap requests:
while (true) {
// Wait for trap event (bitmask in unaff_s5)
event = wait_for_bar_event();
switch (event & 0x3F) {
case 0x01: // BAR1 write access
handle_bar1_write();
break;
case 0x02: // BAR1 read access
handle_bar1_read();
break;
case 0x08: // Aperture configuration
handle_aperture_config();
break;
case 0x10: // ForceBarAccess
handle_force_access();
break;
case 0x20: // Bar1Rest (restore)
handle_bar1_restore();
break;
default:
return ERROR_UNKNOWN_EVENT;
}
}
Event Bitmask
| Bit | Event | Description |
|---|---|---|
| 0 | BAR1_WRITE | Guest VF wrote to BAR1 |
| 1 | BAR1_READ | Guest VF read from BAR1 |
| 3 | APERTURE | Aperture size/offset change |
| 4 | FORCE_ACCESS | ForceBarAccess triggered |
| 5 | BAR1_REST | Restore BAR1 state |
Memory Management
Allocator Arena (0x429B450)
// Allocate backing store for BAR emulation
void *bar_alloc(size_t size) {
// Calls UNK_ram_058A1A9C(0x429B450, size)
// Returns pointer in 0x429B000 region
}
// Free backing store
void bar_free(void *ptr) {
// Calls UNK_ram_05895BF4(0x429B428, ptr)
}
Allocation Sizes
- Standard BAR1 page: 0x1000 (4 KB)
- Aperture buffer: 0x40000 (256 KB) max
- Force access buffer: 0x1000 (4 KB)
Cache Coherency
// Flush cache for DMA
void bar_cache_flush(void *addr, size_t size) {
UNK_ram_05895BF4(0x429B428, addr);
UNK_ram_05895BF4(0x429B428, addr + size);
}
BAR1 Emulation Logic
Write Path (Event 0x01)
int handle_bar1_write(bar_trap_t *trap) {
// 1. Validate offset within aperture
if (trap->offset >= bar1_aperture_size)
return ERROR_OVERFLOW;
// 2. Check ForceBarAccess flag
if (force_bar_access && !(trap->flags & FORCE_ALLOWED))
return ERROR_PERMISSION;
// 3. Translate to backing store
uint8_t *backing = bar1_backing + trap->offset;
// 4. Perform write (1/2/4/8 bytes)
switch (trap->size) {
case 1: *backing = trap->value; break;
case 2: *(uint16_t*)backing = trap->value; break;
case 4: *(uint32_t*)backing = trap->value; break;
case 8: *(uint64_t*)backing = trap->value; break;
}
// 5. Flush to device if needed
if (device_needs_flush)
bar_cache_flush(backing, trap->size);
return OK;
}
Read Path (Event 0x02)
int handle_bar1_read(bar_trap_t *trap) {
if (trap->offset >= bar1_aperture_size)
return ERROR_OVERFLOW;
uint8_t *backing = bar1_backing + trap->offset;
switch (trap->size) {
case 1: *trap->out_value = *backing; break;
case 2: *trap->out_value = *(uint16_t*)backing; break;
case 4: *trap->out_value = *(uint32_t*)backing; break;
case 8: *trap->out_value = *(uint64_t*)backing; break;
}
return OK;
}
Aperture Configuration (Event 0x08)
int handle_aperture_config(bar_config_t *cfg) {
// Validate new aperture
if (cfg->size > MAX_APERTURE_SIZE) // 0x40000
return ERROR_INVALID;
if (cfg->offset & 0xFFF) // Must be 4KB aligned
return ERROR_ALIGNMENT;
// Reallocate backing store if size changed
if (cfg->size != bar1_aperture_size) {
void *new_backing = bar_alloc(cfg->size);
if (!new_backing) return ERROR_NOMEM;
// Copy existing data
memcpy(new_backing, bar1_backing,
min(cfg->size, bar1_aperture_size));
bar_free(bar1_backing);
bar1_backing = new_backing;
bar1_aperture_size = cfg->size;
}
bar1_aperture_offset = cfg->offset;
return OK;
}
ForceBarAccess (Event 0x10)
int handle_force_access(force_access_t *fa) {
// ForceBarAccess allows hypervisor to bypass VF permissions
// Used for live migration, checkpoint/restore
force_bar_access = fa->enable;
force_access_vf = fa->vf_id;
force_access_range = fa->range;
// Allocate shadow buffer for forced operations
if (fa->enable) {
force_buffer = bar_alloc(0x1000);
if (!force_buffer) return ERROR_NOMEM;
} else {
bar_free(force_buffer);
force_buffer = NULL;
}
return OK;
}
Bar1Rest - State Restore (Event 0x20)
int handle_bar1_restore(restore_state_t *rs) {
// Restore BAR1 state from checkpoint
// Used during VF live migration
bar1_aperture_offset = rs->aperture_offset;
bar1_aperture_size = rs->aperture_size;
force_bar_access = rs->force_access;
// Restore backing store from serialized data
if (rs->backing_size > 0) {
void *new_backing = bar_alloc(rs->backing_size);
if (!new_backing) return ERROR_NOMEM;
memcpy(new_backing, rs->backing_data, rs->backing_size);
bar_free(bar1_backing);
bar1_backing = new_backing;
}
return OK;
}
vGPU-IO Integration
Kernel BAR Trap Registration
struct gsp_bar_ops {
int (*bar_trap)(struct gsp_device *gsp,
struct bar_trap_msg *msg);
int (*configure_aperture)(struct gsp_device *gsp,
uint32_t vf_id,
uint64_t offset, uint64_t size);
int (*force_access)(struct gsp_device *gsp,
uint32_t vf_id, bool enable);
int (*save_state)(struct gsp_device *gsp,
uint32_t vf_id, void *buf, size_t *size);
int (*restore_state)(struct gsp_device *gsp,
uint32_t vf_id, void *buf, size_t size);
};
static const struct gsp_bar_ops gsp_bar_ops = {
.bar_trap = gsp_bar_trap_handler,
.configure_aperture = gsp_bar_config_aperture,
.force_access = gsp_bar_force_access,
.save_state = gsp_bar_save_state,
.restore_state = gsp_bar_restore_state,
};
VF BAR Configuration
int gsp_vf_bar_init(struct gsp_vf *vf) {
struct bar_config cfg = {
.vf_id = vf->id,
.bar = 1, // BAR1
.aperture_offset = vf->bar1_offset,
.aperture_size = vf->bar1_size,
.flags = BAR_FLAG_COHERENT,
};
return gsp_rpc_send(vf->gsp, RPC_BAR_TRAP,
BAR_SUBCMD_CONFIG, &cfg, sizeof(cfg));
}
Live Migration Support
// Save BAR state for migration
int gsp_vf_bar_save(struct gsp_vf *vf, void *buf, size_t *size) {
struct bar_save_msg msg = {
.vf_id = vf->id,
.bar = 1,
};
return gsp_rpc_send(vf->gsp, RPC_BAR_TRAP,
BAR_SUBCMD_SAVE, &msg, sizeof(msg),
buf, size);
}
// Restore BAR state on destination
int gsp_vf_bar_restore(struct gsp_vf *vf, void *buf, size_t size) {
struct bar_restore_msg msg = {
.vf_id = vf->id,
.bar = 1,
.data = buf,
.data_size = size,
};
return gsp_rpc_send(vf->gsp, RPC_BAR_TRAP,
BAR_SUBCMD_RESTORE, &msg, sizeof(msg));
}
Error Handling
| Error | Code | Recovery |
|---|---|---|
| OOM (0x51) | Allocator exhausted | Shrink aperture, retry |
| Timeout (0x1E) | Cache flush timeout | Reset BAR, reinitialize |
| Invalid (0x1F) | Bad aperture config | Validate alignment/size |
| Permission (0xFFFF) | ForceAccess violation | Check VF permissions |
| Overflow (0x25) | Offset beyond aperture | Bounds check in VF driver |
Debugging
Key Registers to Monitor
0x04296048 : Global error flag (cRam0000000004296048) 0x0429B750 : Error status (0x111300 offset) 0x429B428 : Cache management base 0x429B450 : Allocator arena base
Log Strings
Search for these in GSP logs:
BAR1- BAR1 accessBar1Rest- State restoreForceBarAccess- Forced accessBar1Aperture- Aperture changesBar1Size- Size queries
Reference
- Handler:
FUN_ram_04cb8188_ram_04cb8188.c(40 KB) - RPC Type: 0x0A (BAR_TRAP)
- Jump Table Entry: 0x057675B7