Difference between revisions of "WPR Management"

From Open-IOV
Jump to navigation Jump to search
(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:
<span id="wpr-writeread-protect-region-management"></span>
= WPR (Write/Read Protect Region) Management =
= WPR (Write/Read Protect Region) Management =


<span id="overview"></span>
<blockquote>'''Historical document — superseded.''' WPR is the '''write-protected region of VRAM reserved for firmware''', not a generic read/write-protect mechanism; the read-protect framing below is historical reverse-engineering material. 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 ==


WPR (Write Protect Region / Read Protect Region) provides memory isolation for vGPU by protecting guest memory regions from unauthorized access. The GSP firmware implements WPR through two handlers at '''0x04F00B0C''' and '''0x04F00C78''' (62 KB each).
WPR (Write Protect Region / Read Protect Region) provides memory isolation for vGPU by protecting guest memory regions from unauthorized access. The GSP firmware implements WPR through two handlers at '''0x04F00B0C''' and '''0x04F00C78''' (62 KB each).
<span id="key-addresses"></span>
 
== Key Addresses ==
== Key Addresses ==


Line 32: Line 32:
|}
|}


<span id="string-references-60-total"></span>
== String References (60 Total) ==
== String References (60 Total) ==


<span id="completion-events"></span>
=== Completion Events ===
=== Completion Events ===


Line 42: Line 40:
NV_WPR_WRITE_COMPLETE  0x5E478C8
NV_WPR_WRITE_COMPLETE  0x5E478C8
NV_WPR_READ_COMPLETE    0x5E478B0</pre>
NV_WPR_READ_COMPLETE    0x5E478B0</pre>
<span id="timeout-events"></span>
 
=== Timeout Events ===
=== Timeout Events ===


Line 49: Line 47:
NV_WPR_WRITE_TIMEOUT    0x5E47868
NV_WPR_WRITE_TIMEOUT    0x5E47868
NV_WPR_READ_TIMEOUT    0x5E47850</pre>
NV_WPR_READ_TIMEOUT    0x5E47850</pre>
<span id="wpr-state-machine"></span>
 
== WPR State Machine ==
== WPR State Machine ==


<span id="handler-1-0x04f00b0c-primary"></span>
=== Handler 1: 0x04F00B0C (Primary) ===
=== Handler 1: 0x04F00B0C (Primary) ===


<syntaxhighlight lang="c">typedef enum {
<pre>typedef enum {
     WPR_STATE_IDLE = 0,
     WPR_STATE_IDLE = 0,
     WPR_STATE_WRITE_PENDING = 1,
     WPR_STATE_WRITE_PENDING = 1,
Line 73: Line 70:
     void *completion_cb;      // Callback on complete
     void *completion_cb;      // Callback on complete
     void *timeout_cb;          // Callback on timeout
     void *timeout_cb;          // Callback on timeout
} wpr_region_t;</syntaxhighlight>
} wpr_region_t;</pre>
<span id="operation-flow"></span>
 
=== Operation Flow ===
=== Operation Flow ===


<span id="write-protect"></span>
==== Write Protect ====
==== Write Protect ====


Line 90: Line 86:
   d. If denied: trigger WPR_WRITE_COMPLETE/NV_WPR_WRITE_COMPLETE
   d. If denied: trigger WPR_WRITE_COMPLETE/NV_WPR_WRITE_COMPLETE
6. On timeout: trigger WPR_WRITE_TIMEOUT/NV_WPR_WRITE_TIMEOUT</pre>
6. On timeout: trigger WPR_WRITE_TIMEOUT/NV_WPR_WRITE_TIMEOUT</pre>
<span id="read-protect"></span>
 
==== Read Protect ====
==== Read Protect ====


Line 100: Line 96:
   c. Trigger WPR_READ_COMPLETE/NV_WPR_READ_COMPLETE
   c. Trigger WPR_READ_COMPLETE/NV_WPR_READ_COMPLETE
4. On timeout: trigger WPR_READ_TIMEOUT/NV_WPR_READ_TIMEOUT</pre>
4. On timeout: trigger WPR_READ_TIMEOUT/NV_WPR_READ_TIMEOUT</pre>
<span id="vbios-parsing-handler-2-0x04f00c78"></span>
 
== VBIOS Parsing (Handler 2: 0x04F00C78) ==
== VBIOS Parsing (Handler 2: 0x04F00C78) ==


The WPR handlers parse VBIOS structures for legacy compatibility:
The WPR handlers parse VBIOS structures for legacy compatibility:


<syntaxhighlight lang="c">int parse_vbios_for_wpr(void *vbios_ptr, size_t size) {
<pre>int parse_vbios_for_wpr(void *vbios_ptr, size_t size) {
     // Search for signatures:
     // Search for signatures:
     // 0xAA55 - Standard VBIOS signature
     // 0xAA55 - Standard VBIOS signature
Line 111: Line 107:
     // 0x5746564E ("WFVN") - WPR version
     // 0x5746564E ("WFVN") - WPR version
      
      
     for (offset = 0; offset < size; offset += 0x1000) {
     for (offset = 0; offset &lt; size; offset += 0x1000) {
         uint32_t sig = *(uint32_t*)(vbios_ptr + offset);
         uint32_t sig = *(uint32_t*)(vbios_ptr + offset);
          
          
Line 124: Line 120:
         }
         }
     }
     }
}</syntaxhighlight>
}</pre>
<span id="integration-with-gsp-subsystems"></span>
 
== Integration with GSP Subsystems ==
== Integration with GSP Subsystems ==


<span id="memory-allocator-0x429b450"></span>
=== Memory Allocator (0x429B450) ===
=== Memory Allocator (0x429B450) ===


<syntaxhighlight lang="c">// Allocate WPR metadata structures
<pre>// Allocate WPR metadata structures
wpr_region_t *wpr_alloc_region {
wpr_region_t *wpr_alloc_region() {
     return UNK_ram_058A1A9C(0x429B450, sizeof(wpr_region_t));
     return UNK_ram_058A1A9C(0x429B450, sizeof(wpr_region_t));
}
}
Line 139: Line 134:
void *wpr_alloc_bounce(size_t size) {
void *wpr_alloc_bounce(size_t size) {
     return UNK_ram_058A1A9C(0x429B450, size);
     return UNK_ram_058A1A9C(0x429B450, size);
}</syntaxhighlight>
}</pre>
<span id="dmacopy-engine-0x0588f9c4-0x05aec86c"></span>
 
=== DMA/Copy Engine (0x0588F9C4, 0x05AEC86C) ===
=== DMA/Copy Engine (0x0588F9C4, 0x05AEC86C) ===


<syntaxhighlight lang="c">// Copy data for WPR emulation
<pre>// Copy data for WPR emulation
int wpr_emulate_access(wpr_region_t *rgn, void *dst, void *src, size_t size) {
int wpr_emulate_access(wpr_region_t *rgn, void *dst, void *src, size_t size) {
     return UNK_ram_0588F9C4(dma_engine, src, dst, size);
     return UNK_ram_0588F9C4(dma_engine, src, dst, size);
}</syntaxhighlight>
}</pre>
<span id="logging-0x05ab7da0"></span>
 
=== Logging (0x05AB7DA0) ===
=== Logging (0x05AB7DA0) ===


<syntaxhighlight lang="c">// Log WPR events
<pre>// Log WPR events
void wpr_log_event(const char *event_str, uint32_t vf_id, uint64_t addr) {
void wpr_log_event(const char *event_str, uint32_t vf_id, uint64_t addr) {
     UNK_ram_05AB7DA0(1, &event_str);  // Log string
     UNK_ram_05AB7DA0(1, &amp;event_str);  // Log string
     UNK_ram_05AB7DA0(2, &vf_id);      // Log VF ID
     UNK_ram_05AB7DA0(2, &amp;vf_id);      // Log VF ID
     UNK_ram_05AB7DA0(3, &addr);      // Log address
     UNK_ram_05AB7DA0(3, &amp;addr);      // Log address
}</syntaxhighlight>
}</pre>
<span id="vgpu-io-integration"></span>
 
== vGPU-IO Integration ==
== vGPU-IO Integration ==


<span id="kernel-wpr-api"></span>
=== Kernel WPR API ===
=== Kernel WPR API ===


<syntaxhighlight lang="c">struct gsp_wpr_ops {
<pre>struct gsp_wpr_ops {
     int (*protect_write)(struct gsp_device *gsp,  
     int (*protect_write)(struct gsp_device *gsp,  
                         uint32_t vf_id,
                         uint32_t vf_id,
Line 181: Line 175:
};
};


static const struct gsp_wpr_ops gsp_wpr_ops = {.protect_write = gsp_wpr_write_protect,.protect_read = gsp_wpr_read_protect,.unprotect = gsp_wpr_unprotect,.set_timeout = gsp_wpr_set_timeout,.register_callback = gsp_wpr_register_callback,
static const struct gsp_wpr_ops gsp_wpr_ops = {
};</syntaxhighlight>
    .protect_write = gsp_wpr_write_protect,
<span id="vf-wpr-lifecycle"></span>
    .protect_read = gsp_wpr_read_protect,
    .unprotect = gsp_wpr_unprotect,
    .set_timeout = gsp_wpr_set_timeout,
    .register_callback = gsp_wpr_register_callback,
};</pre>
 
=== VF WPR Lifecycle ===
=== VF WPR Lifecycle ===


<syntaxhighlight lang="c">// VF initialization: register WPR regions
<pre>// VF initialization: register WPR regions
int gsp_vf_wpr_init(struct gsp_vf *vf) {
int gsp_vf_wpr_init(struct gsp_vf *vf) {
     // Protect VF's page tables
     // Protect VF's page tables
     gsp_wpr_ops.protect_write(vf->gsp, vf->id,
     gsp_wpr_ops.protect_write(vf-&gt;gsp, vf-&gt;id,
                               vf->pt_base, vf->pt_size);
                               vf-&gt;pt_base, vf-&gt;pt_size);
      
      
     // Protect VF's command buffers
     // Protect VF's command buffers
     gsp_wpr_ops.protect_write(vf->gsp, vf->id,
     gsp_wpr_ops.protect_write(vf-&gt;gsp, vf-&gt;id,
                               vf->cmd_base, vf->cmd_size);
                               vf-&gt;cmd_base, vf-&gt;cmd_size);
      
      
     // Set default timeout (10ms)
     // Set default timeout (10ms)
     gsp_wpr_ops.set_timeout(vf->gsp, vf->id, 10000000);
     gsp_wpr_ops.set_timeout(vf-&gt;gsp, vf-&gt;id, 10000000);
      
      
     // Register completion callbacks
     // Register completion callbacks
     gsp_wpr_ops.register_callback(vf->gsp, vf->id,
     gsp_wpr_ops.register_callback(vf-&gt;gsp, vf-&gt;id,
                                   WPR_EVENT_WRITE_COMPLETE,
                                   WPR_EVENT_WRITE_COMPLETE,
                                   vf_wpr_write_complete_cb);
                                   vf_wpr_write_complete_cb);
     gsp_wpr_ops.register_callback(vf->gsp, vf->id,
     gsp_wpr_ops.register_callback(vf-&gt;gsp, vf-&gt;id,
                                   WPR_EVENT_TIMEOUT,
                                   WPR_EVENT_TIMEOUT,
                                   vf_wpr_timeout_cb);
                                   vf_wpr_timeout_cb);
Line 212: Line 211:
// VF cleanup
// VF cleanup
void gsp_vf_wpr_fini(struct gsp_vf *vf) {
void gsp_vf_wpr_fini(struct gsp_vf *vf) {
     gsp_wpr_ops.unprotect(vf->gsp, vf->id, vf->pt_base);
     gsp_wpr_ops.unprotect(vf-&gt;gsp, vf-&gt;id, vf-&gt;pt_base);
     gsp_wpr_ops.unprotect(vf->gsp, vf->id, vf->cmd_base);
     gsp_wpr_ops.unprotect(vf-&gt;gsp, vf-&gt;id, vf-&gt;cmd_base);
     //.. unregister callbacks
     // ... unregister callbacks
}</syntaxhighlight>
}</pre>
<span id="callback-handling"></span>
 
=== Callback Handling ===
=== Callback Handling ===


<syntaxhighlight lang="c">static void vf_wpr_write_complete_cb(struct wpr_event *evt) {
<pre>static void vf_wpr_write_complete_cb(struct wpr_event *evt) {
     struct gsp_vf *vf = evt->vf;
     struct gsp_vf *vf = evt-&gt;vf;
      
      
     // Log the write attempt
     // Log the write attempt
     dev_dbg(vf->dev, "WPR write complete: VF=%u addr=0x%llx\n",
     dev_dbg(vf-&gt;dev, "WPR write complete: VF=%u addr=0x%llx\n",
             vf->id, evt->address);
             vf-&gt;id, evt-&gt;address);
      
      
     // If this was a page table update, invalidate TLB
     // If this was a page table update, invalidate TLB
     if (evt->address >= vf->pt_base &&  
     if (evt-&gt;address &gt;= vf-&gt;pt_base &amp;&amp;
         evt->address < vf->pt_base + vf->pt_size) {
         evt-&gt;address &lt; vf-&gt;pt_base + vf-&gt;pt_size) {
         gsp_tlb_invalidate(vf->gsp, vf->id);
         gsp_tlb_invalidate(vf-&gt;gsp, vf-&gt;id);
     }
     }
}
}


static void vf_wpr_timeout_cb(struct wpr_event *evt) {
static void vf_wpr_timeout_cb(struct wpr_event *evt) {
     struct gsp_vf *vf = evt->vf;
     struct gsp_vf *vf = evt-&gt;vf;
      
      
     dev_warn(vf->dev, "WPR timeout: VF=%u type=%d addr=0x%llx\n",
     dev_warn(vf-&gt;dev, "WPR timeout: VF=%u type=%d addr=0x%llx\n",
             vf->id, evt->type, evt->address);
             vf-&gt;id, evt-&gt;type, evt-&gt;address);
      
      
     // Escalate: reset VF or throttle
     // Escalate: reset VF or throttle
     if (evt->type == WPR_EVENT_WRITE_TIMEOUT) {
     if (evt-&gt;type == WPR_EVENT_WRITE_TIMEOUT) {
         gsp_vf_throttle(vf);
         gsp_vf_throttle(vf);
     } else {
     } else {
         gsp_vf_reset(vf);
         gsp_vf_reset(vf);
     }
     }
}</syntaxhighlight>
}</pre>
<span id="error-codes"></span>
 
== Error Codes ==
== Error Codes ==


Line 284: Line 283:
|}
|}


<span id="debugging"></span>
== Debugging ==
== Debugging ==


<span id="monitor-these-addresses"></span>
=== Monitor These Addresses ===
=== Monitor These Addresses ===


<pre>0x04296048: Global error flag
<pre>0x04296048 : Global error flag
0x0429B750+0x111300: Error status register
0x0429B750+0x111300 : Error status register
0x05E47850-0x05E478F8: WPR string table</pre>
0x05E47850-0x05E478F8 : WPR string table</pre>
<span id="gsp-log-patterns"></span>
 
=== GSP Log Patterns ===
=== GSP Log Patterns ===


Line 304: Line 301:
NV_WPR_WRITE_TIMEOUT  VF=&lt;id&gt; ADDR=&lt;addr&gt;
NV_WPR_WRITE_TIMEOUT  VF=&lt;id&gt; ADDR=&lt;addr&gt;
NV_WPR_READ_TIMEOUT  VF=&lt;id&gt; ADDR=&lt;addr&gt;</pre>
NV_WPR_READ_TIMEOUT  VF=&lt;id&gt; ADDR=&lt;addr&gt;</pre>
<span id="trace-points"></span>
 
=== Trace Points ===
=== Trace Points ===


<syntaxhighlight lang="c">// In kernel driver
<pre>// In kernel driver
trace_gsp_wpr_protect(vf_id, base, size, type);
trace_gsp_wpr_protect(vf_id, base, size, type);
trace_gsp_wpr_event(vf_id, event_type, address, status);
trace_gsp_wpr_event(vf_id, event_type, address, status);
trace_gsp_wpr_timeout(vf_id, address, elapsed_ns);</syntaxhighlight>
trace_gsp_wpr_timeout(vf_id, address, elapsed_ns);</pre>


-----
----


<span id="reference"></span>
== Reference ==
== Reference ==



Revision as of 04:10, 12 October 2026

WPR (Write/Read Protect Region) Management

Historical document — superseded. WPR is the write-protected region of VRAM reserved for firmware, not a generic read/write-protect mechanism; the read-protect framing below is historical reverse-engineering material. Canonical documentation: ../docs/03-architecture/06-host-module-and-hybrid-model.md.

Overview

WPR (Write Protect Region / Read Protect Region) provides memory isolation for vGPU by protecting guest memory regions from unauthorized access. The GSP firmware implements WPR through two handlers at 0x04F00B0C and 0x04F00C78 (62 KB each).

Key Addresses

Handler Address Size Role
WPR Handler 1 0x04F00B0C 62 KB Primary WPR management
WPR Handler 2 0x04F00C78 62 KB Secondary/timeout handling
String Table 60 locations — Completion/timeout strings

String References (60 Total)

Completion Events

WPR_WRITE_COMPLETE      0x5E478F8
WPR_READ_COMPLETE       0x5E478E0
NV_WPR_WRITE_COMPLETE   0x5E478C8
NV_WPR_READ_COMPLETE    0x5E478B0

Timeout Events

WPR_WRITE_TIMEOUT       0x5E47898
WPR_READ_TIMEOUT        0x5E47880
NV_WPR_WRITE_TIMEOUT    0x5E47868
NV_WPR_READ_TIMEOUT     0x5E47850

WPR State Machine

Handler 1: 0x04F00B0C (Primary)

typedef enum {
    WPR_STATE_IDLE = 0,
    WPR_STATE_WRITE_PENDING = 1,
    WPR_STATE_READ_PENDING = 2,
    WPR_STATE_COMPLETE = 3,
    WPR_STATE_TIMEOUT = 4,
    WPR_STATE_ERROR = 0xFFFF
} wpr_state_t;

typedef struct {
    uint64_t region_base;      // Protected region base
    uint64_t region_size;      // Region size (page-aligned)
    uint32_t vf_id;            // Owning VF
    uint32_t flags;            // WPR_WRITE | WPR_READ | WPR_EXECUTE
    wpr_state_t state;
    uint64_t timeout_ns;       // Operation timeout
    void *completion_cb;       // Callback on complete
    void *timeout_cb;          // Callback on timeout
} wpr_region_t;

Operation Flow

Write Protect

1. VF requests WPR_WRITE on region [base, base+size)
2. Handler validates alignment (4KB) and permissions
3. Programs MMU/IOMMU write-protect bits
4. Starts timeout timer (configurable)
5. On GPU write attempt:
   a. Trap to GSP via page fault
   b. Check if VF owns region
   c. If allowed: emulate write, return OK
   d. If denied: trigger WPR_WRITE_COMPLETE/NV_WPR_WRITE_COMPLETE
6. On timeout: trigger WPR_WRITE_TIMEOUT/NV_WPR_WRITE_TIMEOUT

Read Protect

1. VF requests WPR_READ on region
2. Programs MMU/IOMMU read-protect bits
3. On GPU read attempt:
   a. Trap to GSP
   b. Return zero/poison data or emulate
   c. Trigger WPR_READ_COMPLETE/NV_WPR_READ_COMPLETE
4. On timeout: trigger WPR_READ_TIMEOUT/NV_WPR_READ_TIMEOUT

VBIOS Parsing (Handler 2: 0x04F00C78)

The WPR handlers parse VBIOS structures for legacy compatibility:

int parse_vbios_for_wpr(void *vbios_ptr, size_t size) {
    // Search for signatures:
    // 0xAA55 - Standard VBIOS signature
    // 0x57464F4E ("WFON") - WPR enable
    // 0x5746564E ("WFVN") - WPR version
    
    for (offset = 0; offset < size; offset += 0x1000) {
        uint32_t sig = *(uint32_t*)(vbios_ptr + offset);
        
        if (sig == 0xAA55) {
            // Check for WPR structures
            parse_wpr_tables(vbios_ptr + offset);
        }
        else if (sig == 0x57464F4E || sig == 0x5746564E) {
            // WPR enabled in VBIOS
            wpr_vbios_enabled = true;
            wpr_vbios_offset = offset;
        }
    }
}

Integration with GSP Subsystems

Memory Allocator (0x429B450)

// Allocate WPR metadata structures
wpr_region_t *wpr_alloc_region() {
    return UNK_ram_058A1A9C(0x429B450, sizeof(wpr_region_t));
}

// Allocate bounce buffers for emulation
void *wpr_alloc_bounce(size_t size) {
    return UNK_ram_058A1A9C(0x429B450, size);
}

DMA/Copy Engine (0x0588F9C4, 0x05AEC86C)

// Copy data for WPR emulation
int wpr_emulate_access(wpr_region_t *rgn, void *dst, void *src, size_t size) {
    return UNK_ram_0588F9C4(dma_engine, src, dst, size);
}

Logging (0x05AB7DA0)

// Log WPR events
void wpr_log_event(const char *event_str, uint32_t vf_id, uint64_t addr) {
    UNK_ram_05AB7DA0(1, &event_str);  // Log string
    UNK_ram_05AB7DA0(2, &vf_id);      // Log VF ID
    UNK_ram_05AB7DA0(3, &addr);       // Log address
}

vGPU-IO Integration

Kernel WPR API

struct gsp_wpr_ops {
    int (*protect_write)(struct gsp_device *gsp, 
                         uint32_t vf_id,
                         uint64_t base, uint64_t size);
    int (*protect_read)(struct gsp_device *gsp,
                        uint32_t vf_id,
                        uint64_t base, uint64_t size);
    int (*unprotect)(struct gsp_device *gsp,
                     uint32_t vf_id,
                     uint64_t base);
    int (*set_timeout)(struct gsp_device *gsp,
                       uint32_t vf_id,
                       uint64_t timeout_ns);
    int (*register_callback)(struct gsp_device *gsp,
                             uint32_t vf_id,
                             enum wpr_event_type type,
                             void (*cb)(struct wpr_event *));
};

static const struct gsp_wpr_ops gsp_wpr_ops = {
    .protect_write = gsp_wpr_write_protect,
    .protect_read = gsp_wpr_read_protect,
    .unprotect = gsp_wpr_unprotect,
    .set_timeout = gsp_wpr_set_timeout,
    .register_callback = gsp_wpr_register_callback,
};

VF WPR Lifecycle

// VF initialization: register WPR regions
int gsp_vf_wpr_init(struct gsp_vf *vf) {
    // Protect VF's page tables
    gsp_wpr_ops.protect_write(vf->gsp, vf->id,
                              vf->pt_base, vf->pt_size);
    
    // Protect VF's command buffers
    gsp_wpr_ops.protect_write(vf->gsp, vf->id,
                              vf->cmd_base, vf->cmd_size);
    
    // Set default timeout (10ms)
    gsp_wpr_ops.set_timeout(vf->gsp, vf->id, 10000000);
    
    // Register completion callbacks
    gsp_wpr_ops.register_callback(vf->gsp, vf->id,
                                  WPR_EVENT_WRITE_COMPLETE,
                                  vf_wpr_write_complete_cb);
    gsp_wpr_ops.register_callback(vf->gsp, vf->id,
                                  WPR_EVENT_TIMEOUT,
                                  vf_wpr_timeout_cb);
    
    return 0;
}

// VF cleanup
void gsp_vf_wpr_fini(struct gsp_vf *vf) {
    gsp_wpr_ops.unprotect(vf->gsp, vf->id, vf->pt_base);
    gsp_wpr_ops.unprotect(vf->gsp, vf->id, vf->cmd_base);
    // ... unregister callbacks
}

Callback Handling

static void vf_wpr_write_complete_cb(struct wpr_event *evt) {
    struct gsp_vf *vf = evt->vf;
    
    // Log the write attempt
    dev_dbg(vf->dev, "WPR write complete: VF=%u addr=0x%llx\n",
            vf->id, evt->address);
    
    // If this was a page table update, invalidate TLB
    if (evt->address >= vf->pt_base && 
        evt->address < vf->pt_base + vf->pt_size) {
        gsp_tlb_invalidate(vf->gsp, vf->id);
    }
}

static void vf_wpr_timeout_cb(struct wpr_event *evt) {
    struct gsp_vf *vf = evt->vf;
    
    dev_warn(vf->dev, "WPR timeout: VF=%u type=%d addr=0x%llx\n",
             vf->id, evt->type, evt->address);
    
    // Escalate: reset VF or throttle
    if (evt->type == WPR_EVENT_WRITE_TIMEOUT) {
        gsp_vf_throttle(vf);
    } else {
        gsp_vf_reset(vf);
    }
}

Error Codes

Code Name Description
0x1E ETIME Operation timed out
0x1F EDEV Device error
0x25 EOVERFLOW Region too large
0x37 EINVAL Invalid alignment
0x51 ENOMEM Out of memory
0x56 EBUSY Region busy
0xFFFF EPERM Permission denied

Debugging

Monitor These Addresses

0x04296048  : Global error flag
0x0429B750+0x111300 : Error status register
0x05E47850-0x05E478F8 : WPR string table

GSP Log Patterns

WPR_WRITE_COMPLETE    VF=<id> ADDR=<addr>
WPR_READ_COMPLETE     VF=<id> ADDR=<addr>
WPR_WRITE_TIMEOUT     VF=<id> ADDR=<addr>
WPR_READ_TIMEOUT      VF=<id> ADDR=<addr>
NV_WPR_WRITE_COMPLETE VF=<id> ADDR=<addr>
NV_WPR_READ_COMPLETE  VF=<id> ADDR=<addr>
NV_WPR_WRITE_TIMEOUT  VF=<id> ADDR=<addr>
NV_WPR_READ_TIMEOUT   VF=<id> ADDR=<addr>

Trace Points

// In kernel driver
trace_gsp_wpr_protect(vf_id, base, size, type);
trace_gsp_wpr_event(vf_id, event_type, address, status);
trace_gsp_wpr_timeout(vf_id, address, elapsed_ns);

Reference

  • Handler 1: FUN_ram_04f00b0c_ram_04f00b0c.c (62 KB)
  • Handler 2: FUN_ram_04f00c78_ram_04f00c78.c (62 KB)
  • RPC Types: Handled via primary/secondary dispatchers