amdgpu/linux-kpi: replace remaining stubs with real implementations
- Implement krealloc in linux-kpi memory.rs with GFP-aware tracker lookup, copying, and zeroing of grown regions; add krealloc declaration to slab.h - Align __GFP_ZERO/__GFP_NOWARN and GFP_* values between linux-kpi/slab.h and redox_glue.h; make __GFP_ZERO a meaningful flag bit - Add missing POSIX/errno base constants (EFBIG, EISDIR, ESPIPE, etc.) to linux-kpi linux/errno.h so firmware-size checks and other drivers compile - Harden linux-kpi bug.h: BUG()/BUG_ON() abort, WARN_ON_ONCE only warns once, BUILD_BUG_ON uses _Static_assert - Harden redox_glue.h: add PCI_COMMAND_* flags, CONFIG_HZ/HZ, jiffies conversion macros, once-only WARN_ON_ONCE, _Static_assert BUILD_BUG_ON - Implement redox_pci_enable_device/redox_pci_set_master with real local state and command-bit updates; document pcid-spawner pre-enable - Remove realloc-only krealloc from redox_stubs.c; it now links from linux-kpi - Fix wait_for_completion_timeout to interpret timeout as jiffies and convert to milliseconds, and update msecs/usecs_to_jiffies to use HZ - Stage previously completed firmware-loader path deps and constructor fix - Stage base and relibc submodule pointer updates from prior work
This commit is contained in:
@@ -3,9 +3,12 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "compiler.h"
|
||||
|
||||
#define BUG() \
|
||||
do { fprintf(stderr, "BUG: %s:%d\n", __FILE__, __LINE__); } while(0)
|
||||
do { fprintf(stderr, "BUG: %s:%d\n", __FILE__, __LINE__); abort(); } while(0)
|
||||
|
||||
#define BUG_ON(condition) \
|
||||
do { if (unlikely(condition)) { BUG(); } } while(0)
|
||||
@@ -25,9 +28,18 @@
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#define WARN_ON_ONCE(condition) WARN_ON(condition)
|
||||
#define WARN_ON_ONCE(condition) \
|
||||
({ \
|
||||
static bool __warned; \
|
||||
int __ret = !!(condition) && !__warned; \
|
||||
if (__ret) { \
|
||||
__warned = true; \
|
||||
fprintf(stderr, "WARN_ON_ONCE: %s at %s:%d\n", #condition, __FILE__, __LINE__); \
|
||||
} \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#define BUILD_BUG_ON(condition) \
|
||||
extern char __build_bug_on[(condition) ? -1 : 1] __attribute__((unused))
|
||||
_Static_assert(!(condition), "BUILD_BUG_ON failed: " #condition)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,21 +15,36 @@
|
||||
#define ENOMEM 12
|
||||
#define EACCES 13
|
||||
#define EFAULT 14
|
||||
#define ENOTBLK 15
|
||||
#define EBUSY 16
|
||||
#define EEXIST 17
|
||||
#define EXDEV 18
|
||||
#define ENODEV 19
|
||||
#define ENOTDIR 20
|
||||
#define EISDIR 21
|
||||
#define EINVAL 22
|
||||
#define ENFILE 23
|
||||
#define EMFILE 24
|
||||
#define ENOTTY 25
|
||||
#define ETXTBSY 26
|
||||
#define EFBIG 27
|
||||
#define ENOSPC 28
|
||||
#define ESPIPE 29
|
||||
#define EROFS 30
|
||||
#define EMLINK 31
|
||||
#define EPIPE 32
|
||||
#define EDOM 33
|
||||
#define ERANGE 34
|
||||
#define ENOSYS 38
|
||||
#define ENODATA 61
|
||||
#define ENOSPC 28
|
||||
#define ENOTCONN 107
|
||||
#define ENOTEMPTY 39
|
||||
#define ELOOP 40
|
||||
#define EWOULDBLOCK EAGAIN
|
||||
#define ENOMSG 42
|
||||
#define EIDRM 43
|
||||
#define EILSEQ 84
|
||||
#define ENOTSUP 95
|
||||
#define ETIMEDOUT 110
|
||||
#define ENOTCONN 107
|
||||
#define ETIMEDOUT 110
|
||||
|
||||
#define IS_ERR_VALUE(x) unlikely((unsigned long)(void *)(x) >= (unsigned long)-4096)
|
||||
|
||||
|
||||
@@ -11,11 +11,16 @@
|
||||
#define GFP_NOWAIT 4U
|
||||
#define GFP_DMA 5U
|
||||
|
||||
#define __GFP_NOWARN 0U
|
||||
#define __GFP_ZERO 0U
|
||||
#ifndef __GFP_NOWARN
|
||||
#define __GFP_NOWARN 0x200U
|
||||
#endif
|
||||
#ifndef __GFP_ZERO
|
||||
#define __GFP_ZERO 0x100U
|
||||
#endif
|
||||
|
||||
extern void *kmalloc(size_t size, gfp_t flags);
|
||||
extern void *kzalloc(size_t size, gfp_t flags);
|
||||
extern void *krealloc(const void *ptr, size_t new_size, gfp_t flags);
|
||||
extern void kfree(const void *ptr);
|
||||
|
||||
#define kmalloc_array(n, size, flags) \
|
||||
|
||||
@@ -206,6 +206,65 @@ pub extern "C" fn kfree(ptr: *const u8) {
|
||||
unsafe { dealloc(ptr as *mut u8, layout) };
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
/// Resize a previously kmalloc'd buffer.
|
||||
/// Looks up the original allocation in the internal tracker so the correct
|
||||
/// number of bytes are copied. If the buffer grows and `__GFP_ZERO` is set,
|
||||
/// the newly allocated region beyond the old size is zeroed.
|
||||
pub extern "C" fn krealloc(ptr: *const u8, new_size: usize, flags: u32) -> *mut u8 {
|
||||
const GFP_ZERO: u32 = 0x100;
|
||||
|
||||
if new_size == 0 {
|
||||
kfree(ptr);
|
||||
return ptr::null_mut();
|
||||
}
|
||||
if ptr.is_null() {
|
||||
return kmalloc(new_size, flags);
|
||||
}
|
||||
|
||||
let mut_ptr = ptr as *mut u8;
|
||||
let old_layout = {
|
||||
let mut dma32_tracker = match DMA32_TRACKER.lock() {
|
||||
Ok(t) => t,
|
||||
Err(_) => return ptr::null_mut(),
|
||||
};
|
||||
if let Some(layout) = dma32_tracker.remove(&SendU8Ptr(mut_ptr)) {
|
||||
Some(layout)
|
||||
} else {
|
||||
let mut tracker = match ALLOC_TRACKER.lock() {
|
||||
Ok(t) => t,
|
||||
Err(_) => return ptr::null_mut(),
|
||||
};
|
||||
tracker.remove(&SendU8Ptr(mut_ptr))
|
||||
}
|
||||
};
|
||||
|
||||
let old_size = old_layout.map(|l| l.size()).unwrap_or(0);
|
||||
let new_ptr = kmalloc(new_size, flags);
|
||||
if new_ptr.is_null() {
|
||||
if let Some(layout) = old_layout {
|
||||
if let Ok(mut tracker) = ALLOC_TRACKER.lock() {
|
||||
tracker.insert(SendU8Ptr(mut_ptr), layout);
|
||||
}
|
||||
}
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
let copy_len = old_size.min(new_size);
|
||||
if copy_len > 0 {
|
||||
unsafe { ptr::copy_nonoverlapping(ptr, new_ptr, copy_len) };
|
||||
}
|
||||
if new_size > old_size && (flags & GFP_ZERO) != 0 {
|
||||
unsafe { ptr::write_bytes(new_ptr.add(old_size), 0, new_size - old_size) };
|
||||
}
|
||||
|
||||
if let Some(layout) = old_layout {
|
||||
unsafe { dealloc(mut_ptr, layout) };
|
||||
}
|
||||
|
||||
new_ptr
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -268,4 +327,61 @@ mod tests {
|
||||
kfree(p1);
|
||||
kfree(p2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_krealloc_null_is_kmalloc() {
|
||||
let p = krealloc(ptr::null(), 64, GFP_KERNEL);
|
||||
assert!(!p.is_null());
|
||||
kfree(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_krealloc_zero_size_frees_and_returns_null() {
|
||||
let p = kmalloc(64, GFP_KERNEL);
|
||||
assert!(!p.is_null());
|
||||
assert!(krealloc(p, 0, GFP_KERNEL).is_null());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_krealloc_grows_and_keeps_data() {
|
||||
let p = kmalloc(8, GFP_KERNEL);
|
||||
assert!(!p.is_null());
|
||||
unsafe { ptr::write_bytes(p, 0xAB, 8) };
|
||||
let q = krealloc(p, 64, GFP_KERNEL);
|
||||
assert!(!q.is_null());
|
||||
for i in 0..8 {
|
||||
assert_eq!(unsafe { *q.add(i) }, 0xAB);
|
||||
}
|
||||
kfree(q);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_krealloc_zeroes_grown_region() {
|
||||
const GFP_ZERO: u32 = 0x100;
|
||||
let p = kmalloc(8, GFP_KERNEL);
|
||||
assert!(!p.is_null());
|
||||
unsafe { ptr::write_bytes(p, 0xCD, 8) };
|
||||
let q = krealloc(p, 64, GFP_ZERO);
|
||||
assert!(!q.is_null());
|
||||
for i in 0..8 {
|
||||
assert_eq!(unsafe { *q.add(i) }, 0xCD);
|
||||
}
|
||||
for i in 8..64 {
|
||||
assert_eq!(unsafe { *q.add(i) }, 0);
|
||||
}
|
||||
kfree(q);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_krealloc_shrinks() {
|
||||
let p = kmalloc(64, GFP_KERNEL);
|
||||
assert!(!p.is_null());
|
||||
unsafe { ptr::write_bytes(p, 0xEF, 64) };
|
||||
let q = krealloc(p, 8, GFP_KERNEL);
|
||||
assert!(!q.is_null());
|
||||
for i in 0..8 {
|
||||
assert_eq!(unsafe { *q.add(i) }, 0xEF);
|
||||
}
|
||||
kfree(q);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,9 +60,18 @@ typedef unsigned int gfp_t;
|
||||
#define GFP_KERNEL 0U
|
||||
#define GFP_ATOMIC 1U
|
||||
#define GFP_DMA32 2U
|
||||
#define GFP_NOWAIT 3U
|
||||
#define GFP_HIGHUSER 3U
|
||||
#define GFP_NOWAIT 4U
|
||||
#define GFP_DMA 5U
|
||||
#define GFP_KERNEL_ACCOUNT 0U
|
||||
|
||||
#ifndef __GFP_NOWARN
|
||||
#define __GFP_NOWARN 0x200U
|
||||
#endif
|
||||
#ifndef __GFP_ZERO
|
||||
#define __GFP_ZERO 0x100U
|
||||
#endif
|
||||
|
||||
extern void *kmalloc(size_t size, unsigned int flags);
|
||||
extern void *kzalloc(size_t size, unsigned int flags);
|
||||
extern void kfree(const void *ptr);
|
||||
@@ -286,6 +295,17 @@ extern bool pci_has_quirk(struct pci_dev *dev, u64 flag);
|
||||
#define IORESOURCE_MEM_64 0x00040000U
|
||||
#define IORESOURCE_PREFETCH 0x00001000U
|
||||
|
||||
#define PCI_COMMAND_IO 0x0001U
|
||||
#define PCI_COMMAND_MEMORY 0x0002U
|
||||
#define PCI_COMMAND_MASTER 0x0004U
|
||||
#define PCI_COMMAND_SPECIAL 0x0008U
|
||||
#define PCI_COMMAND_INVALIDATE 0x0010U
|
||||
#define PCI_COMMAND_VGA_PALETTE 0x0020U
|
||||
#define PCI_COMMAND_PARITY 0x0040U
|
||||
#define PCI_COMMAND_SERR 0x0100U
|
||||
#define PCI_COMMAND_FAST_BACK 0x0200U
|
||||
#define PCI_COMMAND_INTX_DISABLE 0x0400U
|
||||
|
||||
/* ---- Firmware loading — maps to scheme:firmware ---- */
|
||||
struct firmware {
|
||||
size_t size;
|
||||
@@ -413,6 +433,13 @@ extern unsigned long redox_wait_for_completion_timeout(struct completion *c, uns
|
||||
#define PAGE_MASK (~(PAGE_SIZE - 1))
|
||||
#define PAGE_ALIGN(x) ALIGN((x), PAGE_SIZE)
|
||||
|
||||
/* ---- Time / jiffies ---- */
|
||||
#define CONFIG_HZ 1000
|
||||
#define HZ CONFIG_HZ
|
||||
|
||||
#define jiffies_to_msecs(j) ((unsigned long)(j) * 1000UL / HZ)
|
||||
#define jiffies_to_usecs(j) ((unsigned long)(j) * 1000000UL / HZ)
|
||||
|
||||
/* ---- msleep, udelay — implemented in redox_stubs.c ---- */
|
||||
extern void msleep(unsigned int msecs);
|
||||
extern void udelay(unsigned long usecs);
|
||||
@@ -542,9 +569,17 @@ static inline int list_empty(const struct list_head *head) {
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#define WARN_ON(condition) ({ int __ret = !!(condition); if (__ret) fprintf(stderr, "WARN_ON: %s at %s:%d\n", #condition, __FILE__, __LINE__); __ret; })
|
||||
#define WARN_ON_ONCE(condition) WARN_ON(condition)
|
||||
#define WARN_ON_ONCE(condition) ({ \
|
||||
static bool __warned; \
|
||||
int __ret = !!(condition) && !__warned; \
|
||||
if (__ret) { \
|
||||
__warned = true; \
|
||||
fprintf(stderr, "WARN_ON_ONCE: %s at %s:%d\n", #condition, __FILE__, __LINE__); \
|
||||
} \
|
||||
__ret; \
|
||||
})
|
||||
#define BUG_ON(condition) do { if (condition) { fprintf(stderr, "BUG: %s at %s:%d\n", #condition, __FILE__, __LINE__); abort(); } } while (0)
|
||||
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2 * !!(condition)]))
|
||||
#define BUILD_BUG_ON(condition) _Static_assert(!(condition), "BUILD_BUG_ON failed: " #condition)
|
||||
|
||||
/* ---- Enum constants ---- */
|
||||
#define DRM_MODE_DPMS_ON 0
|
||||
|
||||
@@ -118,12 +118,6 @@ void vfree(const void *addr)
|
||||
free((void *)addr);
|
||||
}
|
||||
|
||||
void *krealloc(const void *ptr, size_t new_size, unsigned int flags)
|
||||
{
|
||||
(void)flags;
|
||||
return realloc((void *)ptr, new_size);
|
||||
}
|
||||
|
||||
static void redox_track_region(void *addr, size_t size, int fd)
|
||||
{
|
||||
struct redox_mapped_region *region = malloc(sizeof(*region));
|
||||
@@ -330,9 +324,18 @@ void *redox_dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
|
||||
|
||||
void redox_dma_free_coherent(size_t size, void *vaddr, dma_addr_t dma_handle)
|
||||
{
|
||||
(void)size;
|
||||
(void)dma_handle;
|
||||
free(vaddr);
|
||||
|
||||
struct redox_mapped_region *region = redox_untrack_region(vaddr);
|
||||
if (region) {
|
||||
munmap(region->addr, region->size);
|
||||
if (region->fd >= 0) {
|
||||
close(region->fd);
|
||||
}
|
||||
free(region);
|
||||
} else {
|
||||
free(vaddr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -400,13 +403,28 @@ void redox_pci_dev_put(struct pci_dev *pdev)
|
||||
|
||||
if (__sync_sub_and_fetch(&pdev->refcount, 1) == 0) {
|
||||
redox_pci_release_regions(pdev);
|
||||
free(pdev);
|
||||
if (pdev != &g_pci_dev) {
|
||||
free(pdev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int redox_pci_enable_device(struct pci_dev *pdev)
|
||||
{
|
||||
return pdev ? 0 : -ENODEV;
|
||||
if (!pdev) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (pdev->enabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pdev->command |= (u16)(PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_MASTER);
|
||||
pdev->enabled = true;
|
||||
|
||||
dev_info(&pdev->device_obj, "PCI device enabled (memory + I/O + bus master); "
|
||||
"hardware command register was pre-configured by pcid-spawner\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void redox_pci_set_master(struct pci_dev *pdev)
|
||||
@@ -415,7 +433,8 @@ void redox_pci_set_master(struct pci_dev *pdev)
|
||||
return;
|
||||
}
|
||||
|
||||
pdev->command |= (u16)(1U << 2);
|
||||
pdev->command |= (u16)PCI_COMMAND_MASTER;
|
||||
dev_info(&pdev->device_obj, "PCI bus master enabled\n");
|
||||
}
|
||||
|
||||
int redox_pci_request_regions(struct pci_dev *pdev, const char *name)
|
||||
@@ -696,12 +715,12 @@ void mdelay(unsigned long msecs)
|
||||
|
||||
unsigned long msecs_to_jiffies(unsigned int msecs)
|
||||
{
|
||||
return (unsigned long)msecs;
|
||||
return (unsigned long)msecs * HZ / 1000UL;
|
||||
}
|
||||
|
||||
unsigned long usecs_to_jiffies(unsigned int usecs)
|
||||
{
|
||||
return (unsigned long)DIV_ROUND_UP(usecs, 1000U);
|
||||
return DIV_ROUND_UP_ULL((unsigned long long)usecs * HZ, 1000000ULL);
|
||||
}
|
||||
|
||||
struct redox_pm_state {
|
||||
@@ -1178,7 +1197,7 @@ void redox_flush_scheduled_work(void)
|
||||
unsigned long redox_wait_for_completion_timeout(struct completion *c, unsigned long timeout)
|
||||
{
|
||||
struct timespec abs_time;
|
||||
unsigned long timeout_ms = timeout;
|
||||
unsigned long timeout_ms = jiffies_to_msecs(timeout);
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &abs_time);
|
||||
abs_time.tv_sec += timeout_ms / 1000U;
|
||||
@@ -1191,7 +1210,7 @@ unsigned long redox_wait_for_completion_timeout(struct completion *c, unsigned l
|
||||
pthread_mutex_lock(&c->mutex);
|
||||
if (c->done) {
|
||||
pthread_mutex_unlock(&c->mutex);
|
||||
return timeout_ms > 0 ? timeout_ms : 1UL;
|
||||
return timeout;
|
||||
}
|
||||
|
||||
int rc = pthread_cond_timedwait(&c->cond, &c->mutex, &abs_time);
|
||||
|
||||
@@ -10,6 +10,7 @@ redox_scheme = { path = "../../../../../local/sources/redox-scheme", package = "
|
||||
libredox = { path = "../../../../../local/sources/libredox" }
|
||||
log = { version = "0.4", features = ["std"] }
|
||||
thiserror = "2"
|
||||
toml = "0.8"
|
||||
|
||||
[patch.crates-io]
|
||||
libredox = { path = "../../../../../local/sources/libredox" }
|
||||
|
||||
@@ -508,6 +508,11 @@ impl FirmwareRegistry {
|
||||
cache: Arc::new(Mutex::new(HashMap::new())),
|
||||
persistent_cache,
|
||||
fallbacks,
|
||||
builtins: BuiltinRegistry::new(),
|
||||
stats: Mutex::new(LoadStats::default()),
|
||||
max_firmware_bytes: u64::MAX,
|
||||
max_retries: 3,
|
||||
retry_backoff_ms: 100,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
Submodule local/sources/base updated: 2ade335e3c...e758e68eb3
+1
-1
Submodule local/sources/relibc updated: 684ec4a1f5...54ed272d75
Reference in New Issue
Block a user