From 01e6fac4d61fdd7fff5433942ec93fc2ea1e4df1 Mon Sep 17 00:00:00 2001 From: Joshua Bakita Date: Wed, 28 Jun 2023 18:24:25 -0400 Subject: Include nvgpu headers These are needed to build on NVIDIA's Jetson boards for the time being. Only a couple structs are required, so it should be fairly easy to remove this dependency at some point in the future. --- include/os/posix/bitmap.c | 227 +++++++++++++++++++++++ include/os/posix/bug.c | 67 +++++++ include/os/posix/clk_arb.c | 198 ++++++++++++++++++++ include/os/posix/cond.c | 55 ++++++ include/os/posix/error_notifier.c | 40 ++++ include/os/posix/firmware.c | 35 ++++ include/os/posix/fuse.c | 54 ++++++ include/os/posix/io.c | 371 +++++++++++++++++++++++++++++++++++++ include/os/posix/kmem.c | 134 ++++++++++++++ include/os/posix/lock.c | 79 ++++++++ include/os/posix/log.c | 95 ++++++++++ include/os/posix/nvgpu.c | 149 +++++++++++++++ include/os/posix/nvlink.c | 33 ++++ include/os/posix/os_posix.h | 58 ++++++ include/os/posix/posix-channel.c | 32 ++++ include/os/posix/posix-comptags.c | 49 +++++ include/os/posix/posix-dma.c | 88 +++++++++ include/os/posix/posix-nvgpu_mem.c | 140 ++++++++++++++ include/os/posix/posix-tsg.c | 28 +++ include/os/posix/posix-vm.c | 52 ++++++ include/os/posix/posix-vpr.c | 19 ++ include/os/posix/rwsem.c | 117 ++++++++++++ include/os/posix/soc.c | 53 ++++++ include/os/posix/stubs.c | 50 +++++ include/os/posix/thread.c | 101 ++++++++++ include/os/posix/timers.c | 169 +++++++++++++++++ 26 files changed, 2493 insertions(+) create mode 100644 include/os/posix/bitmap.c create mode 100644 include/os/posix/bug.c create mode 100644 include/os/posix/clk_arb.c create mode 100644 include/os/posix/cond.c create mode 100644 include/os/posix/error_notifier.c create mode 100644 include/os/posix/firmware.c create mode 100644 include/os/posix/fuse.c create mode 100644 include/os/posix/io.c create mode 100644 include/os/posix/kmem.c create mode 100644 include/os/posix/lock.c create mode 100644 include/os/posix/log.c create mode 100644 include/os/posix/nvgpu.c create mode 100644 include/os/posix/nvlink.c create mode 100644 include/os/posix/os_posix.h create mode 100644 include/os/posix/posix-channel.c create mode 100644 include/os/posix/posix-comptags.c create mode 100644 include/os/posix/posix-dma.c create mode 100644 include/os/posix/posix-nvgpu_mem.c create mode 100644 include/os/posix/posix-tsg.c create mode 100644 include/os/posix/posix-vm.c create mode 100644 include/os/posix/posix-vpr.c create mode 100644 include/os/posix/rwsem.c create mode 100644 include/os/posix/soc.c create mode 100644 include/os/posix/stubs.c create mode 100644 include/os/posix/thread.c create mode 100644 include/os/posix/timers.c (limited to 'include/os/posix') diff --git a/include/os/posix/bitmap.c b/include/os/posix/bitmap.c new file mode 100644 index 0000000..99ba62c --- /dev/null +++ b/include/os/posix/bitmap.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include +#include + +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) + +unsigned long __nvgpu_posix_ffs(unsigned long word) +{ + return (__builtin_ffsl(word) - 1) & + ((sizeof(unsigned long) * 8UL) - 1UL); +} + +unsigned long __nvgpu_posix_fls(unsigned long word) +{ + unsigned long ret; + + if (word == 0UL) { + /* __builtin_clzl() below is undefined for 0, so we have + * to handle that as a special case. + */ + ret = 0UL; + } else { + ret = (sizeof(unsigned long) * 8UL) - __builtin_clzl(word); + } + + return ret; +} + +static unsigned long __find_next_bit(const unsigned long *addr, + unsigned long n, + unsigned long start, + bool invert) +{ + unsigned long idx; + unsigned long w; + unsigned long start_mask; + + /* + * We make a mask we can XOR into the word so that we can invert the + * word without requiring a branch. I.e instead of doing: + * + * w = invert ? ~addr[idx] : addr[idx] + * + * We can do: + * + * w = addr[idx] ^= invert_mask + * + * This saves us a branch every iteration through the loop. Now we can + * always just look for 1s. + */ + unsigned long invert_mask = invert ? ~0UL : 0UL; + + if (start >= n) + return n; + + start_mask = ~0UL << (start & (BITS_PER_LONG - 1)); + + idx = start / BITS_PER_LONG; + w = (addr[idx] ^ invert_mask) & start_mask; + + start = round_up(start, BITS_PER_LONG); + + /* + * Find the first non-zero word taking into account start and + * invert. + */ + while (!w) { + idx++; + start += BITS_PER_LONG; + + w = addr[idx] ^ invert_mask; + } + + return min(n, ffs(w) + idx * BITS_PER_LONG); +} + +unsigned long find_first_bit(const unsigned long *addr, unsigned long size) +{ + return __find_next_bit(addr, size, 0, false); +} + +unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) +{ + return __find_next_bit(addr, size, 0, true); +} + +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + return __find_next_bit(addr, size, offset, false); +} + +static unsigned long find_next_zero_bit(const unsigned long *addr, + unsigned long size, + unsigned long offset) +{ + return __find_next_bit(addr, size, offset, true); +} + +void bitmap_set(unsigned long *map, unsigned int start, int len) +{ + unsigned int end = start + len; + + /* + * Super slow naive implementation. But speed isn't what matters here. + */ + while (start < end) + set_bit(start++, map); +} + +void bitmap_clear(unsigned long *map, unsigned int start, int len) +{ + unsigned int end = start + len; + + while (start < end) + clear_bit(start++, map); +} + +/* + * This is essentially a find-first-fit allocator: this searches a bitmap for + * the first space that is large enough to satisfy the requested size of bits. + * That means that this is not a vary smart allocator. But it is fast relative + * to an allocator that goes looking for an optimal location. + */ +unsigned long bitmap_find_next_zero_area_off(unsigned long *map, + unsigned long size, + unsigned long start, + unsigned int nr, + unsigned long align_mask, + unsigned long align_offset) +{ + unsigned long offs; + + while (start + nr <= size) { + start = find_next_zero_bit(map, size, start); + + start = ALIGN_MASK(start + align_offset, align_mask) - + align_offset; + + /* + * Not enough space left to satisfy the requested area. + */ + if ((start + nr) > size) + return size; + + offs = find_next_bit(map, size, start); + + if ((offs - start) >= nr) + return start; + + start = offs + 1; + } + + return size; +} + +unsigned long bitmap_find_next_zero_area(unsigned long *map, + unsigned long size, + unsigned long start, + unsigned int nr, + unsigned long align_mask) +{ + return bitmap_find_next_zero_area_off(map, size, start, nr, + align_mask, 0); +} + +bool test_bit(int nr, const volatile unsigned long *addr) +{ + return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1))); +} + +bool test_and_set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + volatile unsigned long *p = addr + BIT_WORD(nr); + + return !!(__sync_fetch_and_or(p, mask) & mask); +} + +bool test_and_clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + return !!(__sync_fetch_and_and(p, ~mask) & mask); +} + +void set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + __atomic_or(p, mask); +} + +void clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = BIT_MASK(nr); + unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); + + __atomic_and(p, ~mask); +} diff --git a/include/os/posix/bug.c b/include/os/posix/bug.c new file mode 100644 index 0000000..64f4a6f --- /dev/null +++ b/include/os/posix/bug.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +#include + +__attribute__ ((noreturn)) +static void __hang(void) +{ + nvgpu_err(NULL, "Hanging!"); + + while (1) + ; +} + +static void __dump_stack(unsigned int skip_frames) +{ + return; +} + +void dump_stack(void) +{ + __dump_stack(0); +} + +/* + * Ahhh! A bug! + */ +void __bug(const char *fmt, ...) +{ + nvgpu_err(NULL, "BUG detected!"); + + __hang(); +} + +bool __warn(bool cond, const char *fmt, ...) +{ + if (!cond) + goto done; + + nvgpu_warn(NULL, "WARNING detected!"); + + dump_stack(); + +done: + return cond; +} diff --git a/include/os/posix/clk_arb.c b/include/os/posix/clk_arb.c new file mode 100644 index 0000000..fcba0a2 --- /dev/null +++ b/include/os/posix/clk_arb.c @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +/** + * Stub imlementation of the clk_arb code. Yikes. Much of this probably could be + * commonized if one were to think through the implementation but that is + * probably weeks of work at a minimum. + * + * So for POSIX it will be stubbed. + */ + +int nvgpu_clk_arb_init_arbiter(struct gk20a *g) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_get_arbiter_clk_range(struct gk20a *g, u32 api_domain, + u16 *min_mhz, u16 *max_mhz) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_update_vf_table(struct nvgpu_clk_arb *arb) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_worker_init(struct gk20a *g) +{ + return -ENOSYS; +} + +bool nvgpu_clk_arb_has_active_req(struct gk20a *g) +{ + return false; +} + +int nvgpu_clk_arb_get_arbiter_actual_mhz(struct gk20a *g, + u32 api_domain, u16 *actual_mhz) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_get_arbiter_effective_mhz(struct gk20a *g, + u32 api_domain, u16 *effective_mhz) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_get_arbiter_clk_f_points(struct gk20a *g, + u32 api_domain, + u32 *max_points, u16 *fpoints) +{ + return -ENOSYS; +} + +u32 nvgpu_clk_arb_get_arbiter_clk_domains(struct gk20a *g) +{ + return 0; +} + +bool nvgpu_clk_arb_is_valid_domain(struct gk20a *g, u32 api_domain) +{ + return false; +} + +void nvgpu_clk_arb_cleanup_arbiter(struct gk20a *g) +{ +} + +int nvgpu_clk_arb_install_session_fd(struct gk20a *g, + struct nvgpu_clk_session *session) +{ + return -ENOSYS; +} + + +int nvgpu_clk_arb_init_session(struct gk20a *g, + struct nvgpu_clk_session **_session) +{ + return -ENOSYS; +} + +void nvgpu_clk_arb_release_session(struct gk20a *g, + struct nvgpu_clk_session *session) +{ +} + +int nvgpu_clk_arb_commit_request_fd(struct gk20a *g, + struct nvgpu_clk_session *session, + int request_fd) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_set_session_target_mhz(struct nvgpu_clk_session *session, + int fd, u32 api_domain, u16 target_mhz) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_get_session_target_mhz(struct nvgpu_clk_session *session, + u32 api_domain, u16 *target_mhz) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_install_event_fd(struct gk20a *g, + struct nvgpu_clk_session *session, + int *event_fd, u32 alarm_mask) +{ + return -ENOSYS; +} + +int nvgpu_clk_arb_install_request_fd(struct gk20a *g, + struct nvgpu_clk_session *session, + int *event_fd) +{ + return -ENOSYS; +} + +u32 nvgpu_clk_arb_notify(struct nvgpu_clk_dev *dev, + struct nvgpu_clk_arb_target *target, + u32 alarm) +{ + return 0; +} + +void nvgpu_clk_arb_free_fd(struct nvgpu_ref *refcount) +{ +} + +void nvgpu_clk_arb_schedule_vf_table_update(struct gk20a *g) +{ +} + +int nvgpu_clk_arb_get_current_pstate(struct gk20a *g) +{ + return -ENOSYS; +} + +void nvgpu_clk_arb_pstate_change_lock(struct gk20a *g, bool lock) +{ +} + +void nvgpu_clk_arb_send_thermal_alarm(struct gk20a *g) +{ +} + +void nvgpu_clk_arb_schedule_alarm(struct gk20a *g, u32 alarm) +{ +} + +void nvgpu_clk_arb_set_global_alarm(struct gk20a *g, u32 alarm) +{ +} + +void nvgpu_clk_arb_clear_global_alarm(struct gk20a *g, u32 alarm) +{ +} + +void nvgpu_clk_arb_event_post_event(struct nvgpu_clk_dev *dev) +{ +} + +void nvgpu_clk_arb_worker_enqueue(struct gk20a *g, + struct nvgpu_clk_arb_work_item *work_item) +{ +} + +int nvgpu_clk_notification_queue_alloc(struct gk20a *g, + struct nvgpu_clk_notification_queue *queue, + size_t events_number) +{ + return -ENOSYS; +} diff --git a/include/os/posix/cond.c b/include/os/posix/cond.c new file mode 100644 index 0000000..ca8a2c4 --- /dev/null +++ b/include/os/posix/cond.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +#include + +int nvgpu_cond_init(struct nvgpu_cond *cond) +{ + return -ENOSYS; +} + +int nvgpu_cond_signal(struct nvgpu_cond *cond) +{ + return -ENOSYS; +} + +int nvgpu_cond_signal_interruptible(struct nvgpu_cond *cond) +{ + return -ENOSYS; +} + +int nvgpu_cond_broadcast(struct nvgpu_cond *cond) +{ + return -ENOSYS; +} + +int nvgpu_cond_broadcast_interruptible(struct nvgpu_cond *cond) +{ + return -ENOSYS; +} + +void nvgpu_cond_destroy(struct nvgpu_cond *cond) +{ + +} diff --git a/include/os/posix/error_notifier.c b/include/os/posix/error_notifier.c new file mode 100644 index 0000000..50b4f25 --- /dev/null +++ b/include/os/posix/error_notifier.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +void nvgpu_set_error_notifier_locked(struct channel_gk20a *ch, u32 error) +{ +} + +void nvgpu_set_error_notifier(struct channel_gk20a *ch, u32 error) +{ +} + +void nvgpu_set_error_notifier_if_empty(struct channel_gk20a *ch, u32 error) +{ +} + +bool nvgpu_is_error_notifier_set(struct channel_gk20a *ch, u32 error_notifier) +{ + return false; +} diff --git a/include/os/posix/firmware.c b/include/os/posix/firmware.c new file mode 100644 index 0000000..aedfef9 --- /dev/null +++ b/include/os/posix/firmware.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +struct nvgpu_firmware *nvgpu_request_firmware(struct gk20a *g, + const char *fw_name, + int flags) +{ + return NULL; +} + +void nvgpu_release_firmware(struct gk20a *g, struct nvgpu_firmware *fw) +{ + /* Noop. */ +} diff --git a/include/os/posix/fuse.c b/include/os/posix/fuse.c new file mode 100644 index 0000000..09ec36d --- /dev/null +++ b/include/os/posix/fuse.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +int nvgpu_tegra_get_gpu_speedo_id(struct gk20a *g) +{ + return 0; +} + +void nvgpu_tegra_fuse_write_bypass(struct gk20a *g, u32 val) +{ +} + +void nvgpu_tegra_fuse_write_access_sw(struct gk20a *g, u32 val) +{ +} + +void nvgpu_tegra_fuse_write_opt_gpu_tpc0_disable(struct gk20a *g, u32 val) +{ +} + +void nvgpu_tegra_fuse_write_opt_gpu_tpc1_disable(struct gk20a *g, u32 val) +{ +} + +int nvgpu_tegra_fuse_read_gcplex_config_fuse(struct gk20a *g, u32 *val) +{ + return -ENODEV; +} + +int nvgpu_tegra_fuse_read_reserved_calib(struct gk20a *g, u32 *val) +{ + return -ENODEV; +} diff --git a/include/os/posix/io.c b/include/os/posix/io.c new file mode 100644 index 0000000..8369e73 --- /dev/null +++ b/include/os/posix/io.c @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include + +#include "os_posix.h" + + +/* + * This function sets the IO callbacks to the passed set of callbacks. It + * returns the value of the old IO callback struct pointer. This function + * cannot fail. + * + * This is expected to be called from modules to set up their IO interaction. + */ +struct nvgpu_posix_io_callbacks *nvgpu_posix_register_io( + struct gk20a *g, + struct nvgpu_posix_io_callbacks *io_callbacks) +{ + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + struct nvgpu_posix_io_callbacks *old_io = p->callbacks; + + p->callbacks = io_callbacks; + + return old_io; +} + +void nvgpu_writel(struct gk20a *g, u32 r, u32 v) +{ + struct nvgpu_posix_io_callbacks *callbacks = + nvgpu_os_posix_from_gk20a(g)->callbacks; + + struct nvgpu_reg_access access = { + .addr = r, + .value = v + }; + + if (callbacks == NULL || callbacks->writel == NULL) { + BUG(); + } + + callbacks->writel(g, &access); +} + +void nvgpu_writel_relaxed(struct gk20a *g, u32 r, u32 v) +{ + BUG(); +} + +u32 nvgpu_readl(struct gk20a *g, u32 r) +{ + struct nvgpu_posix_io_callbacks *callbacks = + nvgpu_os_posix_from_gk20a(g)->callbacks; + + struct nvgpu_reg_access access = { + .addr = r, + .value = 0L + }; + + if (callbacks == NULL || callbacks->readl == NULL) { + BUG(); + } + + callbacks->readl(g, &access); + + return access.value; +} + +void nvgpu_writel_loop(struct gk20a *g, u32 r, u32 v) +{ + BUG(); +} + +u32 __nvgpu_readl(struct gk20a *g, u32 r) +{ + struct nvgpu_posix_io_callbacks *callbacks = + nvgpu_os_posix_from_gk20a(g)->callbacks; + + struct nvgpu_reg_access access = { + .addr = r, + .value = 0L + }; + + if (callbacks == NULL || callbacks->__readl == NULL) { + BUG(); + } + + callbacks->__readl(g, &access); + + return access.value; +} + +void nvgpu_bar1_writel(struct gk20a *g, u32 b, u32 v) +{ + struct nvgpu_posix_io_callbacks *callbacks = + nvgpu_os_posix_from_gk20a(g)->callbacks; + + struct nvgpu_reg_access access = { + .addr = b, + .value = v + }; + + if (callbacks == NULL || callbacks->bar1_writel == NULL) { + BUG(); + } + + callbacks->bar1_writel(g, &access); +} + +u32 nvgpu_bar1_readl(struct gk20a *g, u32 b) +{ + struct nvgpu_posix_io_callbacks *callbacks = + nvgpu_os_posix_from_gk20a(g)->callbacks; + + struct nvgpu_reg_access access = { + .addr = b, + .value = 0L + }; + + if (callbacks == NULL || callbacks->bar1_readl == NULL) { + BUG(); + } + + callbacks->bar1_readl(g, &access); + + return access.value; +} + +void nvgpu_usermode_writel(struct gk20a *g, u32 r, u32 v) +{ + struct nvgpu_posix_io_callbacks *callbacks = + nvgpu_os_posix_from_gk20a(g)->callbacks; + + struct nvgpu_reg_access access = { + .addr = r, + .value = v + }; + + if (callbacks == NULL || callbacks->usermode_writel == NULL) { + BUG(); + } + + callbacks->usermode_writel(g, &access); +} + +bool nvgpu_io_exists(struct gk20a *g) +{ + return false; +} + +bool nvgpu_io_valid_reg(struct gk20a *g, u32 r) +{ + return false; +} + +void nvgpu_posix_io_init_reg_space(struct gk20a *g) +{ + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + + p->recording = false; + p->error_code = 0; + nvgpu_init_list_node(&p->reg_space_head); + nvgpu_init_list_node(&p->recorder_head); +} + +int nvgpu_posix_io_get_error_code(struct gk20a *g) +{ + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + + return p->error_code; +} + +void nvgpu_posix_io_reset_error_code(struct gk20a *g) +{ + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + + p->error_code = 0; +} + +/* + * Add a new register space to the list of spaces, defined by a base + * address and a size. + */ +int nvgpu_posix_io_add_reg_space(struct gk20a *g, u32 base, u32 size) +{ + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + struct nvgpu_posix_io_reg_space *new_reg_space = + nvgpu_kzalloc(g, sizeof(struct nvgpu_posix_io_reg_space)); + + if (new_reg_space == NULL) { + return -ENOMEM; + } + + new_reg_space->base = base; + new_reg_space->size = size; + + new_reg_space->data = nvgpu_vzalloc(g, size); + if (new_reg_space->data == NULL) { + return -ENOMEM; + } + + nvgpu_list_add_tail(&new_reg_space->link, &p->reg_space_head); + return 0; +} + +void nvgpu_posix_io_delete_reg_space(struct gk20a *g, u32 base) +{ + struct nvgpu_posix_io_reg_space *reg_space = + nvgpu_posix_io_get_reg_space(g, base); + if (reg_space == NULL) { + /* Invalid space, or already de-allocated */ + return; + } + nvgpu_list_del(®_space->link); + nvgpu_vfree(g, reg_space->data); + nvgpu_kfree(g, reg_space); +} + +/* + * Lookup a register space from a given address. If no register space is found + * this is a bug similar to a translation fault. + */ +struct nvgpu_posix_io_reg_space *nvgpu_posix_io_get_reg_space(struct gk20a *g, + u32 addr) +{ + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + struct nvgpu_posix_io_reg_space *reg_space; + + nvgpu_list_for_each_entry(reg_space, &p->reg_space_head, + nvgpu_posix_io_reg_space, link) { + u32 offset = addr - reg_space->base; + + if ((addr >= reg_space->base) && (offset <= reg_space->size)) { + return reg_space; + } + } + p->error_code = -EFAULT; + nvgpu_err(g, "ABORT for address 0x%x", addr); + return NULL; +} + +void nvgpu_posix_io_writel_reg_space(struct gk20a *g, u32 addr, u32 data) +{ + struct nvgpu_posix_io_reg_space *space = + nvgpu_posix_io_get_reg_space(g, addr); + + if (space != NULL) { + u32 offset = (addr - space->base) / ((u32) sizeof(u32)); + + *(space->data + offset) = data; + } +} + +u32 nvgpu_posix_io_readl_reg_space(struct gk20a *g, u32 addr) +{ + struct nvgpu_posix_io_reg_space *space = + nvgpu_posix_io_get_reg_space(g, addr); + + if (space != NULL) { + u32 offset = (addr - space->base) / ((u32) sizeof(u32)); + + return *(space->data + offset); + } else { + return 0; + } +} + +/* + * Start recording register writes. If this function is called again, + * it will free all previously recorded events. + */ +void nvgpu_posix_io_start_recorder(struct gk20a *g) +{ + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + struct nvgpu_posix_io_reg_access *ptr; + + /* If list already has events, delete them all */ + if (p->recording == true) { + while (!nvgpu_list_empty(&p->recorder_head)) { + ptr = nvgpu_list_first_entry(&p->recorder_head, + nvgpu_posix_io_reg_access, link); + nvgpu_list_del(&ptr->link); + nvgpu_kfree(g, ptr); + } + } + p->recording = true; +} + +void nvgpu_posix_io_record_access(struct gk20a *g, + struct nvgpu_reg_access *access) +{ + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + + if (p->recording == true) { + struct nvgpu_posix_io_reg_access *new_event = nvgpu_kzalloc(g, + sizeof(struct nvgpu_posix_io_reg_access)); + (void) memcpy(&(new_event->access), access, + sizeof(struct nvgpu_reg_access)); + nvgpu_list_add_tail(&new_event->link, &p->recorder_head); + } +} + +/* + * Take an array of accesses and compare to the recorded sequence. Returns true + * if the array matches the recorded sequence. + * If strict mode is false, this function allows extra accesses to be present + * in the recording. + */ +bool nvgpu_posix_io_check_sequence(struct gk20a *g, + struct nvgpu_reg_access *sequence, u32 size, bool strict) +{ + struct nvgpu_os_posix *p = nvgpu_os_posix_from_gk20a(g); + struct nvgpu_posix_io_reg_access *ptr; + u32 i = 0; + + if (p->recording == false) { + return false; + } + + nvgpu_list_for_each_entry(ptr, &p->recorder_head, + nvgpu_posix_io_reg_access, link) { + if ((sequence[i].addr == ptr->access.addr) && + (sequence[i].value == ptr->access.value)) { + i++; + } else { + if (strict == true) { + return false; + } + } + } + + if (i != size) { + /* Either missing or too many accesses */ + return false; + } + + if (&ptr->link == &p->recorder_head) { + /* Identical match */ + return true; + } + + /* Not an identical match */ + if (strict) { + return false; + } else { + return true; + } +} diff --git a/include/os/posix/kmem.c b/include/os/posix/kmem.c new file mode 100644 index 0000000..5fe0aeb --- /dev/null +++ b/include/os/posix/kmem.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +#include +#include +#include + +#include + +struct nvgpu_kmem_cache { + size_t alloc_size; +}; + +/* + * kmem cache emulation: basically just do a regular malloc(). This is slower + * but should not affect a user of kmem cache in the slightest bit. + */ +struct nvgpu_kmem_cache *nvgpu_kmem_cache_create(struct gk20a *g, size_t size) +{ + struct nvgpu_kmem_cache *cache = + malloc(sizeof(struct nvgpu_kmem_cache)); + + if (cache != NULL) + return NULL; + + cache->alloc_size = size; + + return cache; +} + +void nvgpu_kmem_cache_destroy(struct nvgpu_kmem_cache *cache) +{ + free(cache); +} + +void *nvgpu_kmem_cache_alloc(struct nvgpu_kmem_cache *cache) +{ + return malloc(cache->alloc_size); +} + +void nvgpu_kmem_cache_free(struct nvgpu_kmem_cache *cache, void *ptr) +{ + free(ptr); +} + +void *__nvgpu_kmalloc(struct gk20a *g, size_t size, void *ip) +{ + return malloc(size); +} + +void *__nvgpu_kzalloc(struct gk20a *g, size_t size, void *ip) +{ + return calloc(1, size); +} + +void *__nvgpu_kcalloc(struct gk20a *g, size_t n, size_t size, void *ip) +{ + /* + * calloc() implicitly zeros mem. So calloc a single member size bytes + * long. + */ + return calloc(n, size); +} + +void __nvgpu_kfree(struct gk20a *g, void *addr) +{ + free(addr); +} + +/* + * The concept of vmalloc() does not exist in userspace. + */ +void *__nvgpu_vmalloc(struct gk20a *g, unsigned long size, void *ip) +{ + return __nvgpu_kmalloc(g, size, ip); +} + +void *__nvgpu_vzalloc(struct gk20a *g, unsigned long size, void *ip) +{ + return __nvgpu_kzalloc(g, size, ip); +} + +void __nvgpu_vfree(struct gk20a *g, void *addr) +{ + __nvgpu_kfree(g, addr); +} + +void *__nvgpu_big_alloc(struct gk20a *g, size_t size, bool clear) +{ + /* + * Since in userspace vmalloc() == kmalloc() == malloc() we can just + * reuse k[zm]alloc() for this. + */ + return clear ? + __nvgpu_kzalloc(g, size, _NVGPU_GET_IP_) : + __nvgpu_kmalloc(g, size, _NVGPU_GET_IP_); +} + +void nvgpu_big_free(struct gk20a *g, void *p) +{ + __nvgpu_kfree(g, p); +} + +int nvgpu_kmem_init(struct gk20a *g) +{ + /* Nothing to init at the moment. */ + return 0; +} + +void nvgpu_kmem_fini(struct gk20a *g, int flags) +{ + +} diff --git a/include/os/posix/lock.c b/include/os/posix/lock.c new file mode 100644 index 0000000..bca0f04 --- /dev/null +++ b/include/os/posix/lock.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +int nvgpu_mutex_init(struct nvgpu_mutex *mutex) +{ + return pthread_mutex_init(&mutex->lock.mutex, NULL); +} + +void nvgpu_mutex_acquire(struct nvgpu_mutex *mutex) +{ + __nvgpu_posix_lock_acquire(&mutex->lock); +} + +void nvgpu_mutex_release(struct nvgpu_mutex *mutex) +{ + __nvgpu_posix_lock_release(&mutex->lock); +} + +int nvgpu_mutex_tryacquire(struct nvgpu_mutex *mutex) +{ + return __nvgpu_posix_lock_try_acquire(&mutex->lock); +} + +void nvgpu_mutex_destroy(struct nvgpu_mutex *mutex) +{ + pthread_mutex_destroy(&mutex->lock.mutex); +} + +void nvgpu_spinlock_init(struct nvgpu_spinlock *spinlock) +{ + pthread_mutex_init(&spinlock->lock.mutex, NULL); +} + +void nvgpu_spinlock_acquire(struct nvgpu_spinlock *spinlock) +{ + __nvgpu_posix_lock_acquire(&spinlock->lock); +} + +void nvgpu_spinlock_release(struct nvgpu_spinlock *spinlock) +{ + __nvgpu_posix_lock_release(&spinlock->lock); +} + +void nvgpu_raw_spinlock_init(struct nvgpu_raw_spinlock *spinlock) +{ + pthread_mutex_init(&spinlock->lock.mutex, NULL); +} + +void nvgpu_raw_spinlock_acquire(struct nvgpu_raw_spinlock *spinlock) +{ + __nvgpu_posix_lock_acquire(&spinlock->lock); +} + +void nvgpu_raw_spinlock_release(struct nvgpu_raw_spinlock *spinlock) +{ + __nvgpu_posix_lock_release(&spinlock->lock); +} diff --git a/include/os/posix/log.c b/include/os/posix/log.c new file mode 100644 index 0000000..35d2626 --- /dev/null +++ b/include/os/posix/log.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include + +/* + * Define a length for log buffers. This is the buffer that the 'fmt, ...' part + * of __nvgpu_do_log_print() prints into. + */ +#define LOG_BUFFER_LENGTH 160 + +/* + * Keep this roughly the same as the kernel log format. + */ +#define LOG_FMT "nvgpu: %s %33s:%-4d [%-4s] %s\n" + +u64 nvgpu_dbg_mask = NVGPU_DEFAULT_DBG_MASK; + +static const char *log_types[] = { + "ERR", + "WRN", + "DBG", + "INFO", +}; + +static inline const char *nvgpu_log_name(struct gk20a *g) +{ + return "gpu.USS"; +} + +static void __nvgpu_really_print_log(const char *gpu_name, + const char *func_name, int line, + enum nvgpu_log_type type, const char *log) +{ + const char *name = gpu_name ? gpu_name : ""; + const char *log_type = log_types[type]; + + printf(LOG_FMT, name, func_name, line, log_type, log); +} + +__attribute__((format (printf, 5, 6))) +void __nvgpu_log_msg(struct gk20a *g, const char *func_name, int line, + enum nvgpu_log_type type, const char *fmt, ...) +{ + char log[LOG_BUFFER_LENGTH]; + va_list args; + + va_start(args, fmt); + vsnprintf(log, LOG_BUFFER_LENGTH, fmt, args); + va_end(args); + + __nvgpu_really_print_log(nvgpu_log_name(g), + func_name, line, type, log); +} + +__attribute__((format (printf, 5, 6))) +void __nvgpu_log_dbg(struct gk20a *g, u64 log_mask, + const char *func_name, int line, + const char *fmt, ...) +{ + char log[LOG_BUFFER_LENGTH]; + va_list args; + + if ((log_mask & g->log_mask) == 0) + return; + + va_start(args, fmt); + vsnprintf(log, LOG_BUFFER_LENGTH, fmt, args); + va_end(args); + + __nvgpu_really_print_log(nvgpu_log_name(g), + func_name, line, NVGPU_DEBUG, log); +} diff --git a/include/os/posix/nvgpu.c b/include/os/posix/nvgpu.c new file mode 100644 index 0000000..e485ed7 --- /dev/null +++ b/include/os/posix/nvgpu.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "os_posix.h" + +void nvgpu_wait_for_deferred_interrupts(struct gk20a *g) +{ + /* + * No interrupts in userspace so nothing to wait for. + */ +} + +int nvgpu_current_pid(struct gk20a *g) +{ + /* + * In the kernel this gets us the PID of the calling process for IOCTLs. + * But since we are in userspace this doesn't quite mean the same thing. + * This simply returns the PID of the currently running process. + */ + return (int)getpid(); +} + +int nvgpu_current_tid(struct gk20a *g) +{ + /* + * In POSIX thread ID is not the same as a process ID. In Linux threads + * and processes are represented by the same thing, but userspace can't + * really rely on that. + * + * We can, however, get a pthread_t for a given thread. But this + * pthread_t need not have any relation to the underlying system's + * representation of "threads". + */ + return (int)pthread_self(); +} + +void __nvgpu_print_current(struct gk20a *g, const char *func_name, int line, + void *ctx, enum nvgpu_log_type type) +{ + __nvgpu_log_msg(g, func_name, line, type, + "Current process: (nvgpu userspace)"); +} + +/* + * Somewhat meaningless in userspace... + */ +void nvgpu_kernel_restart(void *cmd) +{ + BUG(); +} + +/* + * We have no runtime PM stuff in userspace so these are really just noops. + */ +void gk20a_busy_noresume(struct gk20a *g) +{ +} + +void gk20a_idle_nosuspend(struct gk20a *g) +{ +} + +bool gk20a_check_poweron(struct gk20a *g) +{ + return false; +} + +int gk20a_busy(struct gk20a *g) +{ + nvgpu_atomic_inc(&g->usage_count); + + return 0; +} + +void gk20a_idle(struct gk20a *g) +{ + nvgpu_atomic_dec(&g->usage_count); +} + +/* + * This function aims to initialize enough stuff to make unit testing worth + * while. There are several interfaces and APIs that rely on the struct gk20a's + * state in order to function: logging, for example, but there are many other + * things, too. + * + * Initialize as much of that as possible here. This is meant to be equivalent + * to the kernel space driver's probe function. + */ +struct gk20a *nvgpu_posix_probe(void) +{ + struct gk20a *g; + struct nvgpu_os_posix *p; + int err; + + p = malloc(sizeof(*p)); + if (p == NULL) + return NULL; + + g = &p->g; + + err = nvgpu_kmem_init(g); + if (err != 0) + goto fail; + + return g; + +fail: + free(p); + + return NULL; +} + +void nvgpu_posix_cleanup(struct gk20a *g) +{ + nvgpu_kmem_fini(g, 0); +} diff --git a/include/os/posix/nvlink.c b/include/os/posix/nvlink.c new file mode 100644 index 0000000..c830d6e --- /dev/null +++ b/include/os/posix/nvlink.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +int nvgpu_nvlink_train(struct gk20a *g, u32 link_id, bool from_off) +{ + return -ENOSYS; +} + +int nvgpu_nvlink_enumerate(struct gk20a *g) +{ + return -ENOSYS; +} diff --git a/include/os/posix/os_posix.h b/include/os/posix/os_posix.h new file mode 100644 index 0000000..d403ad5 --- /dev/null +++ b/include/os/posix/os_posix.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef __NVGPU_OS_POSIX_H__ +#define __NVGPU_OS_POSIX_H__ + +#include + +struct nvgpu_posix_io_callbacks; + +struct nvgpu_os_posix { + struct gk20a g; + + + /* + * IO callbacks for handling the nvgpu IO accessors. + */ + struct nvgpu_posix_io_callbacks *callbacks; + + /* + * Memory-mapped register space for unit tests. + */ + struct nvgpu_list_node reg_space_head; + int error_code; + + + /* + * List to record sequence of register writes. + */ + struct nvgpu_list_node recorder_head; + bool recording; +}; + +static inline struct nvgpu_os_posix *nvgpu_os_posix_from_gk20a(struct gk20a *g) +{ + return container_of(g, struct nvgpu_os_posix, g); +} + +#endif diff --git a/include/os/posix/posix-channel.c b/include/os/posix/posix-channel.c new file mode 100644 index 0000000..5e10b1e --- /dev/null +++ b/include/os/posix/posix-channel.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +u32 nvgpu_get_gpfifo_entry_size(void) +{ + /* + * There is no struct nvgpu_gpfifo for us to use yet. But when it's + * defined in userspace this is how big it will be. + */ + return 8; +} diff --git a/include/os/posix/posix-comptags.c b/include/os/posix/posix-comptags.c new file mode 100644 index 0000000..a00246d --- /dev/null +++ b/include/os/posix/posix-comptags.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include + +void gk20a_get_comptags(struct nvgpu_os_buffer *buf, + struct gk20a_comptags *comptags) +{ +} + +int gk20a_alloc_or_get_comptags(struct gk20a *g, + struct nvgpu_os_buffer *buf, + struct gk20a_comptag_allocator *allocator, + struct gk20a_comptags *comptags) +{ + return -ENODEV; +} + +bool gk20a_comptags_start_clear(struct nvgpu_os_buffer *buf) +{ + return false; +} + +void gk20a_comptags_finish_clear(struct nvgpu_os_buffer *buf, + bool clear_successful) +{ +} diff --git a/include/os/posix/posix-dma.c b/include/os/posix/posix-dma.c new file mode 100644 index 0000000..e8c5c9d --- /dev/null +++ b/include/os/posix/posix-dma.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * In userspace vidmem vs sysmem is just a difference in what is placed in the + * aperture field. + */ +static int __nvgpu_do_dma_alloc(struct gk20a *g, unsigned long flags, + size_t size, struct nvgpu_mem *mem, + enum nvgpu_aperture ap) +{ + void *memory = malloc(mem->aligned_size); + + if (memory == NULL) + return -ENOMEM; + + mem->cpu_va = memory; + mem->aperture = ap; + mem->size = size; + mem->aligned_size = PAGE_ALIGN(size); + mem->gpu_va = 0ULL; + mem->skip_wmb = true; + mem->vidmem_alloc = NULL; + mem->allocator = NULL; + + return 0; +} + +bool nvgpu_iommuable(struct gk20a *g) +{ + return false; +} + +int nvgpu_dma_alloc_flags_sys(struct gk20a *g, unsigned long flags, + size_t size, struct nvgpu_mem *mem) +{ + return __nvgpu_do_dma_alloc(g, flags, size, mem, APERTURE_SYSMEM); +} + +int nvgpu_dma_alloc_flags_vid_at(struct gk20a *g, unsigned long flags, + size_t size, struct nvgpu_mem *mem, u64 at) +{ + BUG(); + + return 0; +} + +void nvgpu_dma_free_sys(struct gk20a *g, struct nvgpu_mem *mem) +{ + if (!(mem->mem_flags & NVGPU_MEM_FLAG_SHADOW_COPY)) + free(mem->cpu_va); + + memset(mem, 0, sizeof(*mem)); +} + +void nvgpu_dma_free_vid(struct gk20a *g, struct nvgpu_mem *mem) +{ + BUG(); +} diff --git a/include/os/posix/posix-nvgpu_mem.c b/include/os/posix/posix-nvgpu_mem.c new file mode 100644 index 0000000..26770e4 --- /dev/null +++ b/include/os/posix/posix-nvgpu_mem.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +/* + * These functions are somewhat meaningless. + */ +u64 nvgpu_mem_get_addr(struct gk20a *g, struct nvgpu_mem *mem) +{ + return (u64)(uintptr_t)mem->cpu_va; +} + +u64 nvgpu_mem_get_phys_addr(struct gk20a *g, struct nvgpu_mem *mem) +{ + return (u64)(uintptr_t)mem->cpu_va; +} + +static struct nvgpu_sgl *nvgpu_mem_sgl_next(struct nvgpu_sgl *sgl) +{ + return NULL; +} + +static u64 nvgpu_mem_sgl_phys(struct gk20a *g, struct nvgpu_sgl *sgl) +{ + struct nvgpu_mem *mem = (struct nvgpu_mem *)sgl; + + return (u64)(uintptr_t)mem->cpu_va; +} + +static u64 nvgpu_mem_sgl_dma(struct nvgpu_sgl *sgl) +{ + struct nvgpu_mem *mem = (struct nvgpu_mem *)sgl; + + return (u64)(uintptr_t)mem->cpu_va; +} + +static u64 nvgpu_mem_sgl_length(struct nvgpu_sgl *sgl) +{ + struct nvgpu_mem *mem = (struct nvgpu_mem *)sgl; + + return (u64)mem->aligned_size; +} + +static u64 nvgpu_mem_sgl_gpu_addr(struct gk20a *g, struct nvgpu_sgl *sgl, + struct nvgpu_gmmu_attrs *attrs) +{ + struct nvgpu_mem *mem = (struct nvgpu_mem *)sgl; + + return mem->gpu_va; +} + +static bool nvgpu_mem_sgt_iommuable(struct gk20a *g, struct nvgpu_sgt *sgt) +{ + return nvgpu_iommuable(g); +} + +static void nvgpu_mem_sgt_free(struct gk20a *g, struct nvgpu_sgt *sgt) +{ + nvgpu_kfree(g, sgt); +} + +static struct nvgpu_sgt_ops nvgpu_sgt_posix_ops = { + .sgl_next = nvgpu_mem_sgl_next, + .sgl_phys = nvgpu_mem_sgl_phys, + .sgl_dma = nvgpu_mem_sgl_dma, + .sgl_length = nvgpu_mem_sgl_length, + .sgl_gpu_addr = nvgpu_mem_sgl_gpu_addr, + .sgt_iommuable = nvgpu_mem_sgt_iommuable, + .sgt_free = nvgpu_mem_sgt_free, +}; + +struct nvgpu_sgt *nvgpu_sgt_create_from_mem(struct gk20a *g, + struct nvgpu_mem *mem) +{ + struct nvgpu_sgt *sgt = nvgpu_kzalloc(g, sizeof(*sgt)); + + if (sgt == NULL) + return NULL; + + /* + * The userspace implementation is simple: a single 'entry' (which we + * only need the mem struct to describe). Maybe this could be expanded + * to be more interesting some day. + */ + sgt->sgl = (struct nvgpu_sgl *)mem; + sgt->ops = &nvgpu_sgt_posix_ops; + + return sgt; +} + +int nvgpu_mem_create_from_mem(struct gk20a *g, + struct nvgpu_mem *dest, struct nvgpu_mem *src, + u64 start_page, int nr_pages) +{ + u64 start = start_page * PAGE_SIZE; + u64 size = nr_pages * PAGE_SIZE; + + if (src->aperture != APERTURE_SYSMEM) + return -EINVAL; + + /* Some silly things a caller might do... */ + if (size > src->size) + return -EINVAL; + if ((start + size) > src->size) + return -EINVAL; + + memset(dest, 0, sizeof(*dest)); + + dest->cpu_va = ((char *)src->cpu_va) + start; + dest->mem_flags = src->mem_flags | NVGPU_MEM_FLAG_SHADOW_COPY; + dest->aperture = src->aperture; + dest->skip_wmb = src->skip_wmb; + dest->size = size; + + return 0; +} diff --git a/include/os/posix/posix-tsg.c b/include/os/posix/posix-tsg.c new file mode 100644 index 0000000..d8e3f37 --- /dev/null +++ b/include/os/posix/posix-tsg.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +void gk20a_tsg_event_id_post_event(struct tsg_gk20a *tsg, + int __event_id) +{ +} diff --git a/include/os/posix/posix-vm.c b/include/os/posix/posix-vm.c new file mode 100644 index 0000000..588b956 --- /dev/null +++ b/include/os/posix/posix-vm.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +#include +#include + +#include + +u64 nvgpu_os_buf_get_size(struct nvgpu_os_buffer *os_buf) +{ + return os_buf->size; +} + +struct nvgpu_mapped_buf *nvgpu_vm_find_mapping(struct vm_gk20a *vm, + struct nvgpu_os_buffer *os_buf, + u64 map_addr, + u32 flags, + int kind) +{ + BUG(); + + /* + * No map caching for now. + */ + return NULL; +} + +void nvgpu_vm_unmap_system(struct nvgpu_mapped_buf *mapped_buffer) +{ + free(mapped_buffer->os_priv.buf); +} diff --git a/include/os/posix/posix-vpr.c b/include/os/posix/posix-vpr.c new file mode 100644 index 0000000..07486b1 --- /dev/null +++ b/include/os/posix/posix-vpr.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include + +bool nvgpu_is_vpr_resize_enabled(void) +{ + return false; +} diff --git a/include/os/posix/rwsem.c b/include/os/posix/rwsem.c new file mode 100644 index 0000000..7a696b7 --- /dev/null +++ b/include/os/posix/rwsem.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include + +void nvgpu_rwsem_init(struct nvgpu_rwsem *rwsem) +{ + memset(rwsem, 0, sizeof(*rwsem)); + + nvgpu_spinlock_init(&rwsem->lock); +} + +/* + * Acquire. + */ +void nvgpu_rwsem_down_read(struct nvgpu_rwsem *rwsem) +{ + while (true) { + nvgpu_spinlock_acquire(&rwsem->lock); + + /* + * If there's a writer try again. + */ + if (rwsem->writers < 0) { + nvgpu_spinlock_release(&rwsem->lock); + nvgpu_msleep(10); + continue; + } + + /* + * Otherwise decrement the read counter and return. + */ + rwsem->readers -= 1; + nvgpu_spinlock_release(&rwsem->lock); + return; + } +} + +/* + * Release. + */ +void nvgpu_rwsem_up_read(struct nvgpu_rwsem *rwsem) +{ + nvgpu_spinlock_acquire(&rwsem->lock); + rwsem->readers += 1; + + /* + * Can't be any writers if there was a reader. Also can't be + * a positive number of readers. The increments are always + * downward so if we have a positive number then there is a + * balancing bug. + */ + BUG_ON(rwsem->writers < 0); + BUG_ON(rwsem->readers > 0); + + nvgpu_spinlock_release(&rwsem->lock); +} + +void nvgpu_rwsem_down_write(struct nvgpu_rwsem *rwsem) +{ + while (true) { + nvgpu_spinlock_acquire(&rwsem->lock); + + /* + * If there's a reader or a writer try again. Note: in this very + * simple implementation it's possible for readers to + * indefinitely starve writers. + */ + if (rwsem->writers < 0 || rwsem->readers < 0) { + nvgpu_spinlock_release(&rwsem->lock); + nvgpu_msleep(10); + continue; + } + + rwsem->writers -= 1; + nvgpu_spinlock_release(&rwsem->lock); + return; + } +} + +void nvgpu_rwsem_up_write(struct nvgpu_rwsem *rwsem) +{ + nvgpu_spinlock_acquire(&rwsem->lock); + rwsem->writers += 1; + + /* + * Writers can't be positive: that would be an unbalanced free. Readers + * must be zero - otherwise this writer should never have had access! + */ + BUG_ON(rwsem->writers > 0); + BUG_ON(rwsem->readers != 0); + + nvgpu_spinlock_release(&rwsem->lock); +} diff --git a/include/os/posix/soc.c b/include/os/posix/soc.c new file mode 100644 index 0000000..2346d61 --- /dev/null +++ b/include/os/posix/soc.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +bool nvgpu_platform_is_silicon(struct gk20a *g) +{ + return false; +} + +bool nvgpu_platform_is_simulation(struct gk20a *g) +{ + return false; +} + +bool nvgpu_platform_is_fpga(struct gk20a *g) +{ + return false; +} + +bool nvgpu_is_hypervisor_mode(struct gk20a *g) +{ + return false; +} + +bool nvgpu_is_bpmp_running(struct gk20a *g) +{ + return false; +} + +bool nvgpu_is_soc_t194_a01(struct gk20a *g) +{ + return false; +} diff --git a/include/os/posix/stubs.c b/include/os/posix/stubs.c new file mode 100644 index 0000000..279f4da --- /dev/null +++ b/include/os/posix/stubs.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * Here lie OS stubs that do not have an implementation yet nor has any plans + * for an implementation. + */ + +#include +#include + +#include "gk20a/dbg_gpu_gk20a.h" + +void nvgpu_dbg_session_post_event(struct dbg_session_gk20a *dbg_s) +{ +} + +int nvgpu_ecc_sysfs_init(struct gk20a *g) +{ + return 0; +} + +void nvgpu_ecc_sysfs_remove(struct gk20a *g) +{ +} + +int nvgpu_ltc_alloc_cbc(struct gk20a *g, size_t compbit_backing_size, + bool vidmem_alloc) +{ + return 0; +} diff --git a/include/os/posix/thread.c b/include/os/posix/thread.c new file mode 100644 index 0000000..6fdce13 --- /dev/null +++ b/include/os/posix/thread.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include + +/** + * Use pthreads to mostly emulate the Linux kernel APIs. There are some things + * that are quite different - especially the stop/should_stop notions. In user + * space threads can send signals to one another but of course within the kernel + * that is not as simple. + * + * This could use some nice debugging some day as well. + */ + +/* + * nvgpu thread functions return int. POSIX threads return void *. This little + * wrapper takes the int returning nvgpu thread and instead passes that int back + * through the void * pointer. + */ +static void *__nvgpu_posix_thread_wrapper(void *data) +{ + struct nvgpu_posix_thread_data *nvgpu = data; + + return ERR_PTR(nvgpu->fn(nvgpu->data)); +} + +int nvgpu_thread_create(struct nvgpu_thread *thread, + void *data, + int (*threadfn)(void *data), const char *name) +{ + int ret; + + BUG_ON(thread->running); + + memset(thread, 0, sizeof(*thread)); + + /* + * By subtracting 1 the above memset ensures that we have a zero + * terminated string. + */ + strncpy(thread->tname, name, NVGPU_THREAD_POSIX_MAX_NAMELEN - 1); + + thread->nvgpu.data = data; + thread->nvgpu.fn = threadfn; + + ret = pthread_create(&thread->thread, NULL, + __nvgpu_posix_thread_wrapper, + &thread->nvgpu); + if (ret != 0) + return ret; + +#ifdef _GNU_SOURCE + pthread_setname_np(thread->thread, thread->tname); +#endif + + thread->running = true; + + return 0; +} + +void nvgpu_thread_stop(struct nvgpu_thread *thread) +{ + thread->should_stop = true; +} + +bool nvgpu_thread_should_stop(struct nvgpu_thread *thread) +{ + return thread->should_stop; +} + +bool nvgpu_thread_is_running(struct nvgpu_thread *thread) +{ + return thread->running; +} + +void nvgpu_thread_join(struct nvgpu_thread *thread) +{ + (void) pthread_join(thread->thread, NULL); +} diff --git a/include/os/posix/timers.c b/include/os/posix/timers.c new file mode 100644 index 0000000..c84b0de --- /dev/null +++ b/include/os/posix/timers.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include + +#include +#include +#include + +static s64 now(void) +{ + return nvgpu_current_time_ms(); +} + +/* + * Returns true if a > b; + */ +static bool time_after(s64 a, s64 b) +{ + return a - b > 0; +} + +int nvgpu_timeout_init(struct gk20a *g, struct nvgpu_timeout *timeout, + u32 duration, unsigned long flags) +{ + if (flags & ~NVGPU_TIMER_FLAG_MASK) + return -EINVAL; + + memset(timeout, 0, sizeof(*timeout)); + + timeout->g = g; + timeout->flags = flags; + + if (flags & NVGPU_TIMER_RETRY_TIMER) + timeout->retries.max = duration; + else + timeout->time = nvgpu_current_time_ms() + (s64)duration; + + return 0; +} + +static int __nvgpu_timeout_expired_msg_cpu(struct nvgpu_timeout *timeout, + void *caller, + const char *fmt, va_list args) +{ + struct gk20a *g = timeout->g; + + if (time_after(now(), timeout->time)) { + if (!(timeout->flags & NVGPU_TIMER_SILENT_TIMEOUT)) { + char buf[128]; + + vsnprintf(buf, sizeof(buf), fmt, args); + + nvgpu_err(g, "Timeout detected @ %p %s", caller, buf); + } + + return -ETIMEDOUT; + } + + return 0; +} + +static int __nvgpu_timeout_expired_msg_retry(struct nvgpu_timeout *timeout, + void *caller, + const char *fmt, va_list args) +{ + struct gk20a *g = timeout->g; + + if (timeout->retries.attempted >= timeout->retries.max) { + if (!(timeout->flags & NVGPU_TIMER_SILENT_TIMEOUT)) { + char buf[128]; + + vsnprintf(buf, sizeof(buf), fmt, args); + + nvgpu_err(g, "No more retries @ %p %s", caller, buf); + } + + return -ETIMEDOUT; + } + + timeout->retries.attempted++; + + return 0; +} + +int __nvgpu_timeout_expired_msg(struct nvgpu_timeout *timeout, + void *caller, const char *fmt, ...) +{ + int ret; + va_list args; + + va_start(args, fmt); + if (timeout->flags & NVGPU_TIMER_RETRY_TIMER) + ret = __nvgpu_timeout_expired_msg_retry(timeout, caller, fmt, + args); + else + ret = __nvgpu_timeout_expired_msg_cpu(timeout, caller, fmt, + args); + va_end(args); + + return ret; +} + +int nvgpu_timeout_peek_expired(struct nvgpu_timeout *timeout) +{ + if (timeout->flags & NVGPU_TIMER_RETRY_TIMER) + return timeout->retries.attempted >= timeout->retries.max; + else + return time_after(now(), timeout->time); +} + +void nvgpu_udelay(unsigned int usecs) +{ + BUG(); +} + +void nvgpu_usleep_range(unsigned int min_us, unsigned int max_us) +{ + BUG(); +} + +void nvgpu_msleep(unsigned int msecs) +{ + BUG(); +} + +static inline s64 __nvgpu_current_time_us(void) +{ + struct timeval now; + s64 time_now; + int ret; + + ret = gettimeofday(&now, NULL); + if (ret != 0) + BUG(); + + time_now = ((s64)now.tv_sec * (s64)1000000) + (s64)now.tv_usec; + + return time_now; +} + +s64 nvgpu_current_time_ms(void) +{ + return __nvgpu_current_time_us() / (s64)1000; +} + +u64 nvgpu_hr_timestamp(void) +{ + return __nvgpu_current_time_us(); +} -- cgit v1.2.2