This was the first step of the secure boot refactoring - as Ben asked for some fixes, I now submit it as its own series to make it easier to review (and also because rebasing secure boot on top of this takes time and I don't want to do it until this is validated!). This series attempts to factorize the duplicate falcon-related code into a single library, using the existing nvkm_falcon structure as a basis. Note that this currently makes struct nvkm_falcon used for two different purposes: this fact is acknowledged, and temporary. It just makes it easier to review this first step. Using the library, falcons are now acquired by a given subdev using nvkm_falcon_get(), and released with nvkm_falcon_put(). This allows different engines to share a falcon (as devinit, secboot and pmu will need to do), but forces us to think about falcon ownership and handling them to the next engine properly. A falcon's features are detected using its version and secure registers, and a set of ops are assigned to it. Then the caller can work with higher-level functions to load and execure code, and not care about implementation details. This series also updates gr and secboot use the falcon library as an example. Converting other engines is trivial and should make our use of falcons generally safer. Alexandre Courbot (8): core: constify nv*_printk macros mc: add nvkm_mc_enabled() function core: add falcon library functions secboot: use falcon library definitions secboot: use falcon library gr/gf100: split gf100_gr_init_ctxctl() gr/gf100: use falcon library secboot: remove nvkm_secboot_start() drm/nouveau/include/nvkm/core/client.h | 4 +- drm/nouveau/include/nvkm/core/device.h | 5 +- drm/nouveau/include/nvkm/core/subdev.h | 2 +- drm/nouveau/include/nvkm/engine/falcon.h | 77 +++++++- drm/nouveau/include/nvkm/subdev/mc.h | 1 +- drm/nouveau/include/nvkm/subdev/secboot.h | 16 +- drm/nouveau/nvkm/Kbuild | 1 +- drm/nouveau/nvkm/engine/device/base.c | 5 +- drm/nouveau/nvkm/engine/gr/gf100.c | 262 +++++++++++------------ drm/nouveau/nvkm/engine/gr/gf100.h | 2 +- drm/nouveau/nvkm/engine/gr/gm200.c | 6 +- drm/nouveau/nvkm/falcon/Kbuild | 2 +- drm/nouveau/nvkm/falcon/base.c | 259 +++++++++++++++++++++++- drm/nouveau/nvkm/falcon/falcon_v1.c | 212 +++++++++++++++++++- drm/nouveau/nvkm/falcon/priv.h | 31 +++- drm/nouveau/nvkm/subdev/mc/base.c | 10 +- drm/nouveau/nvkm/subdev/secboot/base.c | 173 +--------------- drm/nouveau/nvkm/subdev/secboot/gm200.c | 182 ++++------------ drm/nouveau/nvkm/subdev/secboot/gm20b.c | 5 +- drm/nouveau/nvkm/subdev/secboot/priv.h | 10 +- 20 files changed, 808 insertions(+), 457 deletions(-) create mode 100644 drm/nouveau/nvkm/falcon/Kbuild create mode 100644 drm/nouveau/nvkm/falcon/base.c create mode 100644 drm/nouveau/nvkm/falcon/falcon_v1.c create mode 100644 drm/nouveau/nvkm/falcon/priv.h -- git-series 0.8.10
Alexandre Courbot
2016-Dec-06 05:35 UTC
[Nouveau] [PATCH 1/8] core: constify nv*_printk macros
Constify the local variables declared in these macros so we can pass const pointers to them. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/core/client.h | 4 ++-- drm/nouveau/include/nvkm/core/device.h | 2 +- drm/nouveau/include/nvkm/core/subdev.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drm/nouveau/include/nvkm/core/client.h b/drm/nouveau/include/nvkm/core/client.h index eaf5905a87a3..99083349c3d4 100644 --- a/drm/nouveau/include/nvkm/core/client.h +++ b/drm/nouveau/include/nvkm/core/client.h @@ -37,8 +37,8 @@ int nvkm_client_notify_put(struct nvkm_client *, int index); /* logging for client-facing objects */ #define nvif_printk(o,l,p,f,a...) do { \ - struct nvkm_object *_object = (o); \ - struct nvkm_client *_client = _object->client; \ + const struct nvkm_object *_object = (o); \ + const struct nvkm_client *_client = _object->client; \ if (_client->debug >= NV_DBG_##l) \ printk(KERN_##p "nouveau: %s:%08x:%08x: "f, _client->name, \ _object->handle, _object->oclass, ##a); \ diff --git a/drm/nouveau/include/nvkm/core/device.h b/drm/nouveau/include/nvkm/core/device.h index 6bc712f32c8b..d426b86e2712 100644 --- a/drm/nouveau/include/nvkm/core/device.h +++ b/drm/nouveau/include/nvkm/core/device.h @@ -262,7 +262,7 @@ extern const struct nvkm_sclass nvkm_udevice_sclass; /* device logging */ #define nvdev_printk_(d,l,p,f,a...) do { \ - struct nvkm_device *_device = (d); \ + const struct nvkm_device *_device = (d); \ if (_device->debug >= (l)) \ dev_##p(_device->dev, f, ##a); \ } while(0) diff --git a/drm/nouveau/include/nvkm/core/subdev.h b/drm/nouveau/include/nvkm/core/subdev.h index 57adefa8b08e..ca9ed3d68f44 100644 --- a/drm/nouveau/include/nvkm/core/subdev.h +++ b/drm/nouveau/include/nvkm/core/subdev.h @@ -32,7 +32,7 @@ void nvkm_subdev_intr(struct nvkm_subdev *); /* subdev logging */ #define nvkm_printk_(s,l,p,f,a...) do { \ - struct nvkm_subdev *_subdev = (s); \ + const struct nvkm_subdev *_subdev = (s); \ if (_subdev->debug >= (l)) { \ dev_##p(_subdev->device->dev, "%s: "f, \ nvkm_subdev_name[_subdev->index], ##a); \ -- git-series 0.8.10
Alexandre Courbot
2016-Dec-06 05:35 UTC
[Nouveau] [PATCH 2/8] mc: add nvkm_mc_enabled() function
Add a function that allows us to query whether a given subdev is currently enabled or not. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/subdev/mc.h | 1 + drm/nouveau/nvkm/subdev/mc/base.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 0 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/mc.h b/drm/nouveau/include/nvkm/subdev/mc.h index 27d25b18d85c..e68ba636741b 100644 --- a/drm/nouveau/include/nvkm/subdev/mc.h +++ b/drm/nouveau/include/nvkm/subdev/mc.h @@ -9,6 +9,7 @@ struct nvkm_mc { void nvkm_mc_enable(struct nvkm_device *, enum nvkm_devidx); void nvkm_mc_disable(struct nvkm_device *, enum nvkm_devidx); +bool nvkm_mc_enabled(struct nvkm_device *, enum nvkm_devidx); void nvkm_mc_reset(struct nvkm_device *, enum nvkm_devidx); void nvkm_mc_intr(struct nvkm_device *, bool *handled); void nvkm_mc_intr_unarm(struct nvkm_device *); diff --git a/drm/nouveau/nvkm/subdev/mc/base.c b/drm/nouveau/nvkm/subdev/mc/base.c index 6b25e25f9eba..09f669ac6630 100644 --- a/drm/nouveau/nvkm/subdev/mc/base.c +++ b/drm/nouveau/nvkm/subdev/mc/base.c @@ -161,6 +161,16 @@ nvkm_mc_enable(struct nvkm_device *device, enum nvkm_devidx devidx) } } +bool +nvkm_mc_enabled(struct nvkm_device *device, enum nvkm_devidx devidx) +{ + u64 pmc_enable = nvkm_mc_reset_mask(device, false, devidx); + + return (pmc_enable != 0) && + ((nvkm_rd32(device, 0x000200) & pmc_enable) == pmc_enable); +} + + static int nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend) { -- git-series 0.8.10
Alexandre Courbot
2016-Dec-06 05:35 UTC
[Nouveau] [PATCH 3/8] core: add falcon library functions
Falcon processors are used in various places of GPU chips. Although there exist different versions of the falcon, and some variants exist, the base set of actions performed on them is the same, which results in lots of duplicated code. This patch consolidates the current nvkm_falcon structure and extends it with the following features: * Ability for an engine to obtain and later release a given falcon, * Abstractions for basic operations (IMEM/DMEM access, start, etc) * Abstractions for secure operations if a falcon is secure Abstractions make it easy to e.g. start a falcon, without having to care about its details. For instance, falcons in secure mode need to be started by writing to a different register. Right now the abstractions variants only cover secure vs. non-secure falcon, but more will come as e.g. SEC2 support is added. This is still a WIP as other functions previously done by engine/falcon.c need to be reimplemented. However this first step allows to keep things simple and to discuss basic design. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/core/device.h | 3 +- drm/nouveau/include/nvkm/engine/falcon.h | 77 +++++++- drm/nouveau/nvkm/Kbuild | 1 +- drm/nouveau/nvkm/engine/device/base.c | 5 +- drm/nouveau/nvkm/falcon/Kbuild | 2 +- drm/nouveau/nvkm/falcon/base.c | 259 ++++++++++++++++++++++++- drm/nouveau/nvkm/falcon/falcon_v1.c | 212 ++++++++++++++++++++- drm/nouveau/nvkm/falcon/priv.h | 31 +++- 8 files changed, 590 insertions(+), 0 deletions(-) create mode 100644 drm/nouveau/nvkm/falcon/Kbuild create mode 100644 drm/nouveau/nvkm/falcon/base.c create mode 100644 drm/nouveau/nvkm/falcon/falcon_v1.c create mode 100644 drm/nouveau/nvkm/falcon/priv.h diff --git a/drm/nouveau/include/nvkm/core/device.h b/drm/nouveau/include/nvkm/core/device.h index d426b86e2712..3751a8991b9b 100644 --- a/drm/nouveau/include/nvkm/core/device.h +++ b/drm/nouveau/include/nvkm/core/device.h @@ -116,6 +116,9 @@ struct nvkm_device { struct notifier_block nb; } acpi; + struct mutex falcon_mutex; + struct list_head falcons; + struct nvkm_bar *bar; struct nvkm_bios *bios; struct nvkm_bus *bus; diff --git a/drm/nouveau/include/nvkm/engine/falcon.h b/drm/nouveau/include/nvkm/engine/falcon.h index e6baf039c269..cfbef43586cd 100644 --- a/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drm/nouveau/include/nvkm/engine/falcon.h @@ -4,13 +4,39 @@ #include <core/engine.h> struct nvkm_fifo_chan; +enum nvkm_falconidx { + NVKM_FALCON_PMU = 0, + NVKM_FALCON_RESERVED = 1, + NVKM_FALCON_FECS = 2, + NVKM_FALCON_GPCCS = 3, + NVKM_FALCON_NVDEC = 4, + NVKM_FALCON_SEC2 = 7, + NVKM_FALCON_END = 11, + NVKM_FALCON_INVALID = 0xffffffff, +}; + +enum nvkm_falcon_dmaidx { + FALCON_DMAIDX_UCODE = 0, + FALCON_DMAIDX_VIRT = 1, + FALCON_DMAIDX_PHYS_VID = 2, + FALCON_DMAIDX_PHYS_SYS_COH = 3, + FALCON_DMAIDX_PHYS_SYS_NCOH = 4, +}; + +extern const char *nvkm_falcon_name[]; + struct nvkm_falcon { const struct nvkm_falcon_func *func; + const struct nvkm_subdev *subdev; struct nvkm_engine engine; + enum nvkm_devidx devidx; + enum nvkm_falconidx id; + struct list_head head; u32 addr; u8 version; u8 secret; + bool debug; struct nvkm_memory *core; bool external; @@ -19,12 +45,14 @@ struct nvkm_falcon { u32 limit; u32 *data; u32 size; + u8 ports; } code; struct { u32 limit; u32 *data; u32 size; + u8 ports; } data; }; @@ -42,6 +70,55 @@ struct nvkm_falcon_func { } data; void (*init)(struct nvkm_falcon *); void (*intr)(struct nvkm_falcon *, struct nvkm_fifo_chan *); + void (*load_imem)(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); + void (*load_dmem)(struct nvkm_falcon *, void *, u32, u32, u8); + void (*read_dmem)(struct nvkm_falcon *, u32, u32, u8, void *); + void (*bind_context)(struct nvkm_falcon *, struct nvkm_gpuobj *); + int (*wait_for_halt)(struct nvkm_falcon *, u32); + void (*set_start_addr)(struct nvkm_falcon *, u32 start_addr); + void (*start)(struct nvkm_falcon *); + int (*enable)(struct nvkm_falcon *falcon); + void (*disable)(struct nvkm_falcon *falcon); + struct nvkm_sclass sclass[]; }; + +struct nvkm_falcon *nvkm_falcon_get(const struct nvkm_subdev *, + enum nvkm_falconidx); +void nvkm_falcon_put(struct nvkm_falcon *falcon); + +static inline u32 +nvkm_falcon_rd32(struct nvkm_falcon *falcon, u32 addr) +{ + return nvkm_rd32(falcon->subdev->device, falcon->addr + addr); +} + +static inline void +nvkm_falcon_wr32(struct nvkm_falcon *falcon, u32 addr, u32 data) +{ + nvkm_wr32(falcon->subdev->device, falcon->addr + addr, data); +} + +static inline u32 +nvkm_falcon_mask(struct nvkm_falcon *falcon, u32 addr, u32 mask, u32 val) +{ + struct nvkm_device *device = falcon->subdev->device; + + return nvkm_mask(device, falcon->addr + addr, mask, val); +} + +void nvkm_falcon_load_imem(struct nvkm_falcon *, void *, u32, u32, u16, u8, + bool); +void nvkm_falcon_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8); +void nvkm_falcon_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *); +void nvkm_falcon_bind_context(struct nvkm_falcon *, struct nvkm_gpuobj *); +void nvkm_falcon_set_start_addr(struct nvkm_falcon *, u32); +void nvkm_falcon_start(struct nvkm_falcon *); +int nvkm_falcon_wait_for_halt(struct nvkm_falcon *, u32); +int nvkm_falcon_enable(struct nvkm_falcon *); +void nvkm_falcon_disable(struct nvkm_falcon *); +int nvkm_falcon_reset(struct nvkm_falcon *); + +void nvkm_falcon_cleanup(struct nvkm_device *); + #endif diff --git a/drm/nouveau/nvkm/Kbuild b/drm/nouveau/nvkm/Kbuild index 2832147b676c..e664378f6eda 100644 --- a/drm/nouveau/nvkm/Kbuild +++ b/drm/nouveau/nvkm/Kbuild @@ -1,3 +1,4 @@ include $(src)/nvkm/core/Kbuild +include $(src)/nvkm/falcon/Kbuild include $(src)/nvkm/subdev/Kbuild include $(src)/nvkm/engine/Kbuild diff --git a/drm/nouveau/nvkm/engine/device/base.c b/drm/nouveau/nvkm/engine/device/base.c index 2cbcffe78c3e..683ffcf0eaa4 100644 --- a/drm/nouveau/nvkm/engine/device/base.c +++ b/drm/nouveau/nvkm/engine/device/base.c @@ -2496,6 +2496,9 @@ nvkm_device_del(struct nvkm_device **pdevice) if (device->func->dtor) *pdevice = device->func->dtor(device); + + nvkm_falcon_cleanup(device); + mutex_unlock(&nv_devices_mutex); kfree(*pdevice); @@ -2715,6 +2718,8 @@ nvkm_device_ctor(const struct nvkm_device_func *func, } mutex_init(&device->mutex); + mutex_init(&device->falcon_mutex); + INIT_LIST_HEAD(&device->falcons); for (i = 0; i < NVKM_SUBDEV_NR; i++) { #define _(s,m) case s: \ diff --git a/drm/nouveau/nvkm/falcon/Kbuild b/drm/nouveau/nvkm/falcon/Kbuild new file mode 100644 index 000000000000..be9d41ad73bf --- /dev/null +++ b/drm/nouveau/nvkm/falcon/Kbuild @@ -0,0 +1,2 @@ +nvkm-y += nvkm/falcon/base.o +nvkm-y += nvkm/falcon/falcon_v1.o diff --git a/drm/nouveau/nvkm/falcon/base.c b/drm/nouveau/nvkm/falcon/base.c new file mode 100644 index 000000000000..efef9fc63407 --- /dev/null +++ b/drm/nouveau/nvkm/falcon/base.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2016, 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 "priv.h" + +#include <subdev/mc.h> + +const char * +nvkm_falcon_name[] = { + [NVKM_FALCON_PMU] = "PMU", + [NVKM_FALCON_RESERVED] = "<reserved>", + [NVKM_FALCON_FECS] = "FECS", + [NVKM_FALCON_GPCCS] = "GPCCS", + [NVKM_FALCON_NVDEC] = "NVDEC", + [NVKM_FALCON_SEC2] = "SEC2", + [NVKM_FALCON_END] = "<invalid>", +}; + +static const struct { + enum nvkm_devidx devidx; + u32 addr; +} falcon_props[] = { + [NVKM_FALCON_PMU] = { NVKM_SUBDEV_PMU, 0x10a000 }, + [NVKM_FALCON_FECS] = { NVKM_ENGINE_GR, 0x409000 }, + [NVKM_FALCON_GPCCS] = { NVKM_ENGINE_GR, 0x41a000 }, + [NVKM_FALCON_NVDEC] = { NVKM_ENGINE_NVDEC, 0x84000 }, + [NVKM_FALCON_SEC2] = { NVKM_ENGINE_SEC, 0x87000 }, + [NVKM_FALCON_END] = { NVKM_SUBDEV_NR, 0x0 }, +}; + +static struct nvkm_falcon * +nvkm_falcon_find(const struct nvkm_subdev *subdev, enum nvkm_falconidx id) +{ + struct nvkm_device *device = subdev->device; + struct nvkm_falcon *falcon; + + list_for_each_entry(falcon, &device->falcons, head) { + if (falcon->id == id) + return falcon; + } + + return NULL; +} + +struct nvkm_falcon * +nvkm_falcon_get(const struct nvkm_subdev *subdev, enum nvkm_falconidx id) +{ + struct nvkm_device *device = subdev->device; + struct nvkm_falcon *falcon; + + if (falcon_props[id].addr == 0x0) + return ERR_PTR(-EINVAL); + + mutex_lock(&device->falcon_mutex); + + falcon = nvkm_falcon_find(subdev, id); + + /* Create the falcon structure if using it for the first time */ + if (!falcon) { + u32 reg; + + falcon = kzalloc(sizeof(*falcon), GFP_KERNEL); + if (!falcon) { + mutex_unlock(&device->falcon_mutex); + return ERR_PTR(-ENOMEM); + } + + INIT_LIST_HEAD(&falcon->head); + falcon->id = id; + falcon->addr = falcon_props[id].addr; + falcon->devidx = falcon_props[id].devidx; + + /* Get falcon version and characteristics */ + reg = nvkm_rd32(device, falcon->addr + 0x12c); + falcon->version = reg & 0xf; + falcon->secret = (reg >> 4) & 0x3; + falcon->code.ports = (reg >> 8) & 0xf; + falcon->data.ports = (reg >> 12) & 0xf; + + reg = nvkm_rd32(device, falcon->addr + 0x108); + falcon->code.limit = (reg & 0x1ff) << 8; + falcon->data.limit = (reg & 0x3fe00) >> 1; + + reg = nvkm_rd32(device, falcon->addr + 0xc08); + falcon->debug = (reg >> 20) & 0x1; + + if (falcon->secret == 0) + falcon->func = &nvkm_falcon_v1_func; + else + falcon->func = &nvkm_falcon_v1_secure_func; + + list_add(&falcon->head, &device->falcons); + } else if (falcon->subdev) { + nvkm_error(subdev, "%s falcon already acquired by %s!\n", + nvkm_falcon_name[id], + nvkm_subdev_name[falcon->subdev->index]); + mutex_unlock(&device->falcon_mutex); + return ERR_PTR(-EAGAIN); + } + + falcon->subdev = subdev; + + mutex_unlock(&device->falcon_mutex); + + nvkm_debug(subdev, "acquired %s falcon\n", nvkm_falcon_name[id]); + + return falcon; +} + +void +nvkm_falcon_put(struct nvkm_falcon *falcon) +{ + const struct nvkm_subdev *subdev = falcon->subdev; + struct nvkm_device *device = subdev->device; + enum nvkm_falconidx id = falcon->id; + + mutex_lock(&device->falcon_mutex); + + if (!falcon->subdev) + nvkm_warn(subdev, "trying to release non-acquired falcon %s\n", + nvkm_falcon_name[id]); + else + nvkm_debug(subdev, "released %s falcon\n", + nvkm_falcon_name[id]); + + falcon->subdev = NULL; + + mutex_unlock(&device->falcon_mutex); +} + +void +nvkm_falcon_cleanup(struct nvkm_device *device) +{ + struct nvkm_falcon *falcon, *n; + + list_for_each_entry_safe(falcon, n, &device->falcons, head) { + if (falcon->subdev) + nvdev_warn(device, + "falcon %s still held by %s at exit time\n", + nvkm_falcon_name[falcon->id], + nvkm_subdev_name[falcon->subdev->index]); + list_del(&falcon->head); + kfree(falcon); + } +} + +void +nvkm_falcon_load_imem(struct nvkm_falcon *falcon, void *data, u32 start, + u32 size, u16 tag, u8 port, bool secure) +{ + if (secure && !falcon->secret) { + nvkm_warn(falcon->subdev, + "writing with secure tag on a non-secure falcon!\n"); + return; + } + + falcon->func->load_imem(falcon, data, start, size, tag, port, + secure); +} + +void +nvkm_falcon_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start, + u32 size, u8 port) +{ + falcon->func->load_dmem(falcon, data, start, size, port); +} + +void +nvkm_falcon_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, u8 port, + void *data) +{ + falcon->func->read_dmem(falcon, start, size, port, data); +} + +void +nvkm_falcon_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *inst) +{ + if (!falcon->func->bind_context) { + nvkm_error(falcon->subdev, + "Context binding not supported on this falcon!\n"); + return; + } + + falcon->func->bind_context(falcon, inst); +} + +void +nvkm_falcon_set_start_addr(struct nvkm_falcon *falcon, u32 start_addr) +{ + falcon->func->set_start_addr(falcon, start_addr); +} + +void +nvkm_falcon_start(struct nvkm_falcon *falcon) +{ + falcon->func->start(falcon); +} + +int +nvkm_falcon_enable(struct nvkm_falcon *falcon) +{ + struct nvkm_device *device = falcon->subdev->device; + int ret; + + nvkm_mc_enable(device, falcon->devidx); + ret = falcon->func->enable(falcon); + if (ret) { + nvkm_mc_disable(device, falcon->devidx); + return ret; + } + + return 0; +} + +void +nvkm_falcon_disable(struct nvkm_falcon *falcon) +{ + struct nvkm_device *device = falcon->subdev->device; + + /* already disabled, return or wait_idle will timeout */ + if (!nvkm_mc_enabled(device, falcon->devidx)) + return; + + falcon->func->disable(falcon); + + nvkm_mc_disable(device, falcon->devidx); +} + +int +nvkm_falcon_reset(struct nvkm_falcon *falcon) +{ + nvkm_falcon_disable(falcon); + return nvkm_falcon_enable(falcon); +} + +int +nvkm_falcon_wait_for_halt(struct nvkm_falcon *falcon, u32 ms) +{ + return falcon->func->wait_for_halt(falcon, ms); +} diff --git a/drm/nouveau/nvkm/falcon/falcon_v1.c b/drm/nouveau/nvkm/falcon/falcon_v1.c new file mode 100644 index 000000000000..25a791f0fb9a --- /dev/null +++ b/drm/nouveau/nvkm/falcon/falcon_v1.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2016, 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 "priv.h" +#include <core/gpuobj.h> +#include <core/memory.h> +#include <subdev/timer.h> + +static void +nvkm_falcon_v1_load_imem(struct nvkm_falcon *falcon, void *data, u32 start, + u32 size, u16 tag, u8 port, bool secure) +{ + struct nvkm_device *device = falcon->subdev->device; + u32 base = falcon->addr; + u32 reg; + int i; + + reg = start | BIT(24) | (secure ? BIT(28) : 0); + nvkm_wr32(device, base + 0x180 + (port * 16), reg); + for (i = 0; i < size / 4; i++) { + /* write new tag every 256B */ + if ((i & 0x3f) == 0) { + nvkm_wr32(device, base + 0x188, tag); + tag++; + } + nvkm_wr32(device, base + 0x184, ((u32 *)data)[i]); + } +} + +static void +nvkm_falcon_v1_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start, + u32 size, u8 port) +{ + struct nvkm_device *device = falcon->subdev->device; + u32 base = falcon->addr; + int i; + + nvkm_wr32(device, base + 0x1c0 + (port * 16), start | (0x1 << 24)); + for (i = 0; i < size / 4; i++) + nvkm_wr32(device, base + 0x1c4, ((u32 *)data)[i]); +} + +static void +nvkm_falcon_v1_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, + u8 port, void *data) +{ + struct nvkm_device *device = falcon->subdev->device; + u32 base = falcon->addr; + int i; + + nvkm_wr32(device, base + 0x1c0 + (port * 16), start | (0x1 << 25)); + for (i = 0; i < size / 4; i++) + ((u32 *)data)[i] = nvkm_rd32(device, base + 0x1c4); +} + +static void +nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *ctx) +{ + u32 inst_loc; + + /* disable instance block binding */ + if (ctx == NULL) { + nvkm_falcon_wr32(falcon, 0x10c, 0x0); + return; + } + + nvkm_falcon_wr32(falcon, 0x10c, 0x1); + + /* setup apertures - virtual */ + nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_UCODE, 0x4); + nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_VIRT, 0x0); + /* setup apertures - physical */ + nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_PHYS_VID, 0x4); + nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_PHYS_SYS_COH, 0x5); + nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_PHYS_SYS_NCOH, 0x6); + + /* Set context */ + if (nvkm_memory_target(ctx->memory) == NVKM_MEM_TARGET_VRAM) + inst_loc = 0x0; /* FB */ + else + inst_loc = 0x3; /* Non-coherent sysmem */ + + /* Enable context */ + nvkm_falcon_mask(falcon, 0x048, 0x1, 0x1); + nvkm_falcon_wr32(falcon, 0x480, + ((ctx->addr >> 12) & 0xfffffff) | + (inst_loc << 28) | (1 << 30)); +} + +static void +nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *falcon, u32 start_addr) +{ + nvkm_falcon_wr32(falcon, 0x104, start_addr); +} + +static void +nvkm_falcon_v1_start(struct nvkm_falcon *falcon) +{ + nvkm_falcon_wr32(falcon, 0x100, 0x2); +} + +static void +nvkm_falcon_v1_secure_start(struct nvkm_falcon *falcon) +{ + u32 reg = nvkm_falcon_rd32(falcon, 0x100); + + if (reg & BIT(6)) + nvkm_falcon_wr32(falcon, 0x130, 0x2); + else + nvkm_falcon_wr32(falcon, 0x100, 0x2); +} + +static int +nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *falcon, u32 ms) +{ + struct nvkm_device *device = falcon->subdev->device; + int ret; + + ret = nvkm_wait_msec(device, ms, falcon->addr + 0x100, 0x10, 0x10); + if (ret < 0) + return ret; + + return 0; +} + +static int +falcon_v1_wait_idle(struct nvkm_falcon *falcon) +{ + struct nvkm_device *device = falcon->subdev->device; + int ret; + + ret = nvkm_wait_msec(device, 10, falcon->addr + 0x04c, 0xffff, 0x0); + if (ret < 0) + return ret; + + return 0; +} + +static int +nvkm_falcon_v1_enable(struct nvkm_falcon *falcon) +{ + struct nvkm_device *device = falcon->subdev->device; + int ret; + + ret = nvkm_wait_msec(device, 10, falcon->addr + 0x10c, 0x6, 0x0); + if (ret < 0) { + nvkm_error(falcon->subdev, "Falcon mem scrubbing timeout\n"); + return ret; + } + + ret = falcon_v1_wait_idle(falcon); + if (ret) + return ret; + + /* enable IRQs */ + nvkm_falcon_wr32(falcon, 0x010, 0xff); + + return 0; +} + +static void +nvkm_falcon_v1_disable(struct nvkm_falcon *falcon) +{ + /* disable IRQs and wait for any previous code to complete */ + nvkm_falcon_wr32(falcon, 0x014, 0xff); + falcon_v1_wait_idle(falcon); +} + +const struct nvkm_falcon_func +nvkm_falcon_v1_func = { + .load_imem = nvkm_falcon_v1_load_imem, + .load_dmem = nvkm_falcon_v1_load_dmem, + .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_context = nvkm_falcon_v1_bind_context, + .start = nvkm_falcon_v1_start, + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, + .enable = nvkm_falcon_v1_enable, + .disable = nvkm_falcon_v1_disable, + .set_start_addr = nvkm_falcon_v1_set_start_addr, +}; + +const struct nvkm_falcon_func +nvkm_falcon_v1_secure_func = { + .load_imem = nvkm_falcon_v1_load_imem, + .load_dmem = nvkm_falcon_v1_load_dmem, + .read_dmem = nvkm_falcon_v1_read_dmem, + .bind_context = nvkm_falcon_v1_bind_context, + .start = nvkm_falcon_v1_secure_start, + .wait_for_halt = nvkm_falcon_v1_wait_for_halt, + .enable = nvkm_falcon_v1_enable, + .disable = nvkm_falcon_v1_disable, + .set_start_addr = nvkm_falcon_v1_set_start_addr, +}; diff --git a/drm/nouveau/nvkm/falcon/priv.h b/drm/nouveau/nvkm/falcon/priv.h new file mode 100644 index 000000000000..f30729f14ad3 --- /dev/null +++ b/drm/nouveau/nvkm/falcon/priv.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, 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 __NVKM_CORE_FALCON_PRIV_H +#define __NVKM_CORE_FALCON_PRIV_H + +#include <engine/falcon.h> + +extern const struct nvkm_falcon_func nvkm_falcon_v1_func; +extern const struct nvkm_falcon_func nvkm_falcon_v1_secure_func; + +#endif -- git-series 0.8.10
Alexandre Courbot
2016-Dec-06 05:35 UTC
[Nouveau] [PATCH 4/8] secboot: use falcon library definitions
Use the definitions provided by the falcon library instead of re-defining our own. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/subdev/secboot.h | 12 +----- drm/nouveau/nvkm/engine/gr/gf100.c | 16 ++++---- drm/nouveau/nvkm/engine/gr/gm200.c | 6 +-- drm/nouveau/nvkm/subdev/secboot/base.c | 18 ++++----- drm/nouveau/nvkm/subdev/secboot/gm200.c | 49 +++++++++--------------- drm/nouveau/nvkm/subdev/secboot/gm20b.c | 4 +- drm/nouveau/nvkm/subdev/secboot/priv.h | 9 ++-- 7 files changed, 47 insertions(+), 67 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/secboot.h b/drm/nouveau/include/nvkm/subdev/secboot.h index b04c38c07761..fe0b849ac94e 100644 --- a/drm/nouveau/include/nvkm/subdev/secboot.h +++ b/drm/nouveau/include/nvkm/subdev/secboot.h @@ -24,15 +24,7 @@ #define __NVKM_SECURE_BOOT_H__ #include <core/subdev.h> - -enum nvkm_secboot_falcon { - NVKM_SECBOOT_FALCON_PMU = 0, - NVKM_SECBOOT_FALCON_RESERVED = 1, - NVKM_SECBOOT_FALCON_FECS = 2, - NVKM_SECBOOT_FALCON_GPCCS = 3, - NVKM_SECBOOT_FALCON_END = 4, - NVKM_SECBOOT_FALCON_INVALID = 0xffffffff, -}; +#include <engine/falcon.h> /** * @base: base IO address of the falcon performing secure boot @@ -48,7 +40,7 @@ struct nvkm_secboot { }; #define nvkm_secboot(p) container_of((p), struct nvkm_secboot, subdev) -bool nvkm_secboot_is_managed(struct nvkm_secboot *, enum nvkm_secboot_falcon); +bool nvkm_secboot_is_managed(struct nvkm_secboot *, enum nvkm_falconidx); int nvkm_secboot_reset(struct nvkm_secboot *, u32 falcon); int nvkm_secboot_start(struct nvkm_secboot *, u32 falcon); diff --git a/drm/nouveau/nvkm/engine/gr/gf100.c b/drm/nouveau/nvkm/engine/gr/gf100.c index 60a1b5c8214b..b8095ca89352 100644 --- a/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1464,16 +1464,16 @@ gf100_gr_init_ctxctl(struct gf100_gr *gr) nvkm_mc_unk260(device, 0); /* securely-managed falcons must be reset using secure boot */ - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) - ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_FECS); + if (nvkm_secboot_is_managed(sb, NVKM_FALCON_FECS)) + ret = nvkm_secboot_reset(sb, NVKM_FALCON_FECS); else gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c, &gr->fuc409d); if (ret) return ret; - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) - ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_GPCCS); + if (nvkm_secboot_is_managed(sb, NVKM_FALCON_GPCCS)) + ret = nvkm_secboot_reset(sb, NVKM_FALCON_GPCCS); else gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac, &gr->fuc41ad); @@ -1487,12 +1487,12 @@ gf100_gr_init_ctxctl(struct gf100_gr *gr) nvkm_wr32(device, 0x41a10c, 0x00000000); nvkm_wr32(device, 0x40910c, 0x00000000); - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS)) - nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_GPCCS); + if (nvkm_secboot_is_managed(sb, NVKM_FALCON_GPCCS)) + nvkm_secboot_start(sb, NVKM_FALCON_GPCCS); else nvkm_wr32(device, 0x41a100, 0x00000002); - if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS)) - nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_FECS); + if (nvkm_secboot_is_managed(sb, NVKM_FALCON_FECS)) + nvkm_secboot_start(sb, NVKM_FALCON_FECS); else nvkm_wr32(device, 0x409100, 0x00000002); if (nvkm_msec(device, 2000, diff --git a/drm/nouveau/nvkm/engine/gr/gm200.c b/drm/nouveau/nvkm/engine/gr/gm200.c index 6435f1257572..7f4de8e3c643 100644 --- a/drm/nouveau/nvkm/engine/gr/gm200.c +++ b/drm/nouveau/nvkm/engine/gr/gm200.c @@ -184,14 +184,12 @@ gm200_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, return ret; /* Load firmwares for non-secure falcons */ - if (!nvkm_secboot_is_managed(device->secboot, - NVKM_SECBOOT_FALCON_FECS)) { + if (!nvkm_secboot_is_managed(device->secboot, NVKM_FALCON_FECS)) { if ((ret = gf100_gr_ctor_fw(gr, "gr/fecs_inst", &gr->fuc409c)) || (ret = gf100_gr_ctor_fw(gr, "gr/fecs_data", &gr->fuc409d))) return ret; } - if (!nvkm_secboot_is_managed(device->secboot, - NVKM_SECBOOT_FALCON_GPCCS)) { + if (!nvkm_secboot_is_managed(device->secboot, NVKM_FALCON_GPCCS)) { if ((ret = gf100_gr_ctor_fw(gr, "gr/gpccs_inst", &gr->fuc41ac)) || (ret = gf100_gr_ctor_fw(gr, "gr/gpccs_data", &gr->fuc41ad))) return ret; diff --git a/drm/nouveau/nvkm/subdev/secboot/base.c b/drm/nouveau/nvkm/subdev/secboot/base.c index 314be2192b7d..ad3767236475 100644 --- a/drm/nouveau/nvkm/subdev/secboot/base.c +++ b/drm/nouveau/nvkm/subdev/secboot/base.c @@ -26,11 +26,11 @@ static const char * managed_falcons_names[] = { - [NVKM_SECBOOT_FALCON_PMU] = "PMU", - [NVKM_SECBOOT_FALCON_RESERVED] = "<reserved>", - [NVKM_SECBOOT_FALCON_FECS] = "FECS", - [NVKM_SECBOOT_FALCON_GPCCS] = "GPCCS", - [NVKM_SECBOOT_FALCON_END] = "<invalid>", + [NVKM_FALCON_PMU] = "PMU", + [NVKM_FALCON_RESERVED] = "<reserved>", + [NVKM_FALCON_FECS] = "FECS", + [NVKM_FALCON_GPCCS] = "GPCCS", + [NVKM_FALCON_END] = "<invalid>", }; /* @@ -190,8 +190,7 @@ nvkm_secboot_start(struct nvkm_secboot *sb, u32 falcon) * nvkm_secboot_is_managed() - check whether a given falcon is securely-managed */ bool -nvkm_secboot_is_managed(struct nvkm_secboot *secboot, - enum nvkm_secboot_falcon fid) +nvkm_secboot_is_managed(struct nvkm_secboot *secboot, enum nvkm_falconidx fid) { if (!secboot) return false; @@ -260,7 +259,7 @@ nvkm_secboot_ctor(const struct nvkm_secboot_func *func, /* setup the performing falcon's base address and masks */ switch (func->boot_falcon) { - case NVKM_SECBOOT_FALCON_PMU: + case NVKM_FALCON_PMU: sb->devidx = NVKM_SUBDEV_PMU; sb->base = 0x10a000; break; @@ -270,8 +269,7 @@ nvkm_secboot_ctor(const struct nvkm_secboot_func *func, }; nvkm_debug(&sb->subdev, "securely managed falcons:\n"); - for_each_set_bit(fid, &sb->func->managed_falcons, - NVKM_SECBOOT_FALCON_END) + for_each_set_bit(fid, &sb->func->managed_falcons, NVKM_FALCON_END) nvkm_debug(&sb->subdev, "- %s\n", managed_falcons_names[fid]); return 0; diff --git a/drm/nouveau/nvkm/subdev/secboot/gm200.c b/drm/nouveau/nvkm/subdev/secboot/gm200.c index ec48e4ace37a..718cfa129a82 100644 --- a/drm/nouveau/nvkm/subdev/secboot/gm200.c +++ b/drm/nouveau/nvkm/subdev/secboot/gm200.c @@ -87,14 +87,6 @@ #include <core/firmware.h> #include <subdev/fb.h> -enum { - FALCON_DMAIDX_UCODE = 0, - FALCON_DMAIDX_VIRT = 1, - FALCON_DMAIDX_PHYS_VID = 2, - FALCON_DMAIDX_PHYS_SYS_COH = 3, - FALCON_DMAIDX_PHYS_SYS_NCOH = 4, -}; - /** * struct fw_bin_header - header of firmware files * @bin_magic: always 0x3b1d14f0 @@ -296,7 +288,7 @@ struct ls_ucode_img_desc { */ struct ls_ucode_img { struct list_head node; - enum nvkm_secboot_falcon falcon_id; + enum nvkm_falconidx falcon_id; struct ls_ucode_img_desc ucode_desc; u32 *ucode_header; @@ -530,15 +522,14 @@ typedef int (*lsf_load_func)(struct nvkm_subdev *, struct ls_ucode_img *); static int ls_ucode_img_load_fecs(struct nvkm_subdev *subdev, struct ls_ucode_img *img) { - return ls_ucode_img_load_generic(subdev, img, "fecs", - NVKM_SECBOOT_FALCON_FECS); + return ls_ucode_img_load_generic(subdev, img, "fecs", NVKM_FALCON_FECS); } static int ls_ucode_img_load_gpccs(struct nvkm_subdev *subdev, struct ls_ucode_img *img) { return ls_ucode_img_load_generic(subdev, img, "gpccs", - NVKM_SECBOOT_FALCON_GPCCS); + NVKM_FALCON_GPCCS); } /** @@ -564,9 +555,9 @@ ls_ucode_img_load(struct nvkm_subdev *subdev, lsf_load_func load_func) } static const lsf_load_func lsf_load_funcs[] = { - [NVKM_SECBOOT_FALCON_END] = NULL, /* reserve enough space */ - [NVKM_SECBOOT_FALCON_FECS] = ls_ucode_img_load_fecs, - [NVKM_SECBOOT_FALCON_GPCCS] = ls_ucode_img_load_gpccs, + [NVKM_FALCON_END] = NULL, /* reserve enough space */ + [NVKM_FALCON_FECS] = ls_ucode_img_load_fecs, + [NVKM_FALCON_GPCCS] = ls_ucode_img_load_gpccs, }; /** @@ -685,7 +676,7 @@ ls_ucode_img_fill_headers(struct gm200_secboot *gsb, struct ls_ucode_img *img, lhdr->flags = LSF_FLAG_DMACTL_REQ_CTX; /* GPCCS will be loaded using PRI */ - if (img->falcon_id == NVKM_SECBOOT_FALCON_GPCCS) + if (img->falcon_id == NVKM_FALCON_GPCCS) lhdr->flags |= LSF_FLAG_FORCE_PRIV_LOAD; /* Align (size bloat) and save off BL descriptor size */ @@ -794,7 +785,7 @@ ls_ucode_mgr_write_wpr(struct gm200_secboot *gsb, struct ls_ucode_mgr *mgr, pos += sizeof(img->wpr_header); } - nvkm_wo32(wpr_blob, pos, NVKM_SECBOOT_FALCON_INVALID); + nvkm_wo32(wpr_blob, pos, NVKM_FALCON_INVALID); nvkm_done(wpr_blob); @@ -824,7 +815,7 @@ gm200_secboot_prepare_ls_blob(struct gm200_secboot *gsb) /* Load all LS blobs */ for_each_set_bit(falcon_id, &gsb->base.func->managed_falcons, - NVKM_SECBOOT_FALCON_END) { + NVKM_FALCON_END) { struct ls_ucode_img *img; img = ls_ucode_img_load(&sb->subdev, lsf_load_funcs[falcon_id]); @@ -1258,7 +1249,7 @@ done: * falcons should have their LS firmware loaded and be ready to run. */ int -gm200_secboot_reset(struct nvkm_secboot *sb, enum nvkm_secboot_falcon falcon) +gm200_secboot_reset(struct nvkm_secboot *sb, enum nvkm_falconidx falcon) { struct gm200_secboot *gsb = gm200_secboot(sb); int ret; @@ -1276,12 +1267,12 @@ gm200_secboot_reset(struct nvkm_secboot *sb, enum nvkm_secboot_falcon falcon) * Once we have proper PMU firmware and support, this will be changed * to a proper call to the PMU method. */ - if (falcon != NVKM_SECBOOT_FALCON_FECS) + if (falcon != NVKM_FALCON_FECS) goto end; /* If WPR is set and we have an unload blob, run it to unlock WPR */ if (gsb->acr_unload_blob && - gsb->falcon_state[NVKM_SECBOOT_FALCON_FECS] != NON_SECURE) { + gsb->falcon_state[NVKM_FALCON_FECS] != NON_SECURE) { ret = gm200_secboot_run_hs_blob(gsb, gsb->acr_unload_blob, &gsb->acr_unload_bl_desc); if (ret) @@ -1300,16 +1291,16 @@ end: } int -gm200_secboot_start(struct nvkm_secboot *sb, enum nvkm_secboot_falcon falcon) +gm200_secboot_start(struct nvkm_secboot *sb, enum nvkm_falconidx falcon) { struct gm200_secboot *gsb = gm200_secboot(sb); int base; switch (falcon) { - case NVKM_SECBOOT_FALCON_FECS: + case NVKM_FALCON_FECS: base = 0x409000; break; - case NVKM_SECBOOT_FALCON_GPCCS: + case NVKM_FALCON_GPCCS: base = 0x41a000; break; default: @@ -1373,11 +1364,11 @@ gm200_secboot_fini(struct nvkm_secboot *sb, bool suspend) /* Run the unload blob to unprotect the WPR region */ if (gsb->acr_unload_blob && - gsb->falcon_state[NVKM_SECBOOT_FALCON_FECS] != NON_SECURE) + gsb->falcon_state[NVKM_FALCON_FECS] != NON_SECURE) ret = gm200_secboot_run_hs_blob(gsb, gsb->acr_unload_blob, &gsb->acr_unload_bl_desc); - for (i = 0; i < NVKM_SECBOOT_FALCON_END; i++) + for (i = 0; i < NVKM_FALCON_END; i++) gsb->falcon_state[i] = NON_SECURE; return ret; @@ -1409,9 +1400,9 @@ gm200_secboot = { .fini = gm200_secboot_fini, .reset = gm200_secboot_reset, .start = gm200_secboot_start, - .managed_falcons = BIT(NVKM_SECBOOT_FALCON_FECS) | - BIT(NVKM_SECBOOT_FALCON_GPCCS), - .boot_falcon = NVKM_SECBOOT_FALCON_PMU, + .managed_falcons = BIT(NVKM_FALCON_FECS) | + BIT(NVKM_FALCON_GPCCS), + .boot_falcon = NVKM_FALCON_PMU, }; /** diff --git a/drm/nouveau/nvkm/subdev/secboot/gm20b.c b/drm/nouveau/nvkm/subdev/secboot/gm20b.c index d5395ebfe8d3..66a1d01f45ce 100644 --- a/drm/nouveau/nvkm/subdev/secboot/gm20b.c +++ b/drm/nouveau/nvkm/subdev/secboot/gm20b.c @@ -192,8 +192,8 @@ gm20b_secboot = { .init = gm20b_secboot_init, .reset = gm200_secboot_reset, .start = gm200_secboot_start, - .managed_falcons = BIT(NVKM_SECBOOT_FALCON_FECS), - .boot_falcon = NVKM_SECBOOT_FALCON_PMU, + .managed_falcons = BIT(NVKM_FALCON_FECS), + .boot_falcon = NVKM_FALCON_PMU, }; int diff --git a/drm/nouveau/nvkm/subdev/secboot/priv.h b/drm/nouveau/nvkm/subdev/secboot/priv.h index a9a8a0e1017e..f77b69219b44 100644 --- a/drm/nouveau/nvkm/subdev/secboot/priv.h +++ b/drm/nouveau/nvkm/subdev/secboot/priv.h @@ -25,16 +25,17 @@ #include <subdev/secboot.h> #include <subdev/mmu.h> +#include <engine/falcon.h> struct nvkm_secboot_func { int (*init)(struct nvkm_secboot *); int (*fini)(struct nvkm_secboot *, bool suspend); void *(*dtor)(struct nvkm_secboot *); - int (*reset)(struct nvkm_secboot *, enum nvkm_secboot_falcon); - int (*start)(struct nvkm_secboot *, enum nvkm_secboot_falcon); + int (*reset)(struct nvkm_secboot *, enum nvkm_falconidx); + int (*start)(struct nvkm_secboot *, enum nvkm_falconidx); /* ID of the falcon that will perform secure boot */ - enum nvkm_secboot_falcon boot_falcon; + enum nvkm_falconidx boot_falcon; /* Bit-mask of IDs of managed falcons */ unsigned long managed_falcons; }; @@ -191,7 +192,7 @@ struct gm200_secboot { RESET, /* In low-secure mode and running */ RUNNING, - } falcon_state[NVKM_SECBOOT_FALCON_END]; + } falcon_state[NVKM_FALCON_END]; bool firmware_ok; }; -- git-series 0.8.10
Use the falcon library functions in secure boot. This removes a lot of code and makes the secure boot flow easier to understand as no register is directly accessed. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/subdev/secboot.h | 3 +- drm/nouveau/nvkm/subdev/secboot/base.c | 152 +---------------------- drm/nouveau/nvkm/subdev/secboot/gm200.c | 114 +++++------------ drm/nouveau/nvkm/subdev/secboot/priv.h | 2 +- 4 files changed, 45 insertions(+), 226 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/secboot.h b/drm/nouveau/include/nvkm/subdev/secboot.h index fe0b849ac94e..7ead4cab363b 100644 --- a/drm/nouveau/include/nvkm/subdev/secboot.h +++ b/drm/nouveau/include/nvkm/subdev/secboot.h @@ -35,8 +35,7 @@ struct nvkm_secboot { const struct nvkm_secboot_func *func; struct nvkm_subdev subdev; - enum nvkm_devidx devidx; - u32 base; + bool debug; }; #define nvkm_secboot(p) container_of((p), struct nvkm_secboot, subdev) diff --git a/drm/nouveau/nvkm/subdev/secboot/base.c b/drm/nouveau/nvkm/subdev/secboot/base.c index ad3767236475..bf23349e1edd 100644 --- a/drm/nouveau/nvkm/subdev/secboot/base.c +++ b/drm/nouveau/nvkm/subdev/secboot/base.c @@ -24,138 +24,6 @@ #include <subdev/mc.h> #include <subdev/timer.h> -static const char * -managed_falcons_names[] = { - [NVKM_FALCON_PMU] = "PMU", - [NVKM_FALCON_RESERVED] = "<reserved>", - [NVKM_FALCON_FECS] = "FECS", - [NVKM_FALCON_GPCCS] = "GPCCS", - [NVKM_FALCON_END] = "<invalid>", -}; - -/* - * Helper falcon functions - */ - -static int -falcon_clear_halt_interrupt(struct nvkm_device *device, u32 base) -{ - int ret; - - /* clear halt interrupt */ - nvkm_mask(device, base + 0x004, 0x10, 0x10); - /* wait until halt interrupt is cleared */ - ret = nvkm_wait_msec(device, 10, base + 0x008, 0x10, 0x0); - if (ret < 0) - return ret; - - return 0; -} - -static int -falcon_wait_idle(struct nvkm_device *device, u32 base) -{ - int ret; - - ret = nvkm_wait_msec(device, 10, base + 0x04c, 0xffff, 0x0); - if (ret < 0) - return ret; - - return 0; -} - -static int -nvkm_secboot_falcon_enable(struct nvkm_secboot *sb) -{ - struct nvkm_device *device = sb->subdev.device; - int ret; - - /* enable engine */ - nvkm_mc_enable(device, sb->devidx); - ret = nvkm_wait_msec(device, 10, sb->base + 0x10c, 0x6, 0x0); - if (ret < 0) { - nvkm_error(&sb->subdev, "Falcon mem scrubbing timeout\n"); - nvkm_mc_disable(device, sb->devidx); - return ret; - } - - ret = falcon_wait_idle(device, sb->base); - if (ret) - return ret; - - /* enable IRQs */ - nvkm_wr32(device, sb->base + 0x010, 0xff); - nvkm_mc_intr_mask(device, sb->devidx, true); - - return 0; -} - -static int -nvkm_secboot_falcon_disable(struct nvkm_secboot *sb) -{ - struct nvkm_device *device = sb->subdev.device; - - /* disable IRQs and wait for any previous code to complete */ - nvkm_mc_intr_mask(device, sb->devidx, false); - nvkm_wr32(device, sb->base + 0x014, 0xff); - - falcon_wait_idle(device, sb->base); - - /* disable engine */ - nvkm_mc_disable(device, sb->devidx); - - return 0; -} - -int -nvkm_secboot_falcon_reset(struct nvkm_secboot *sb) -{ - int ret; - - ret = nvkm_secboot_falcon_disable(sb); - if (ret) - return ret; - - ret = nvkm_secboot_falcon_enable(sb); - if (ret) - return ret; - - return 0; -} - -/** - * nvkm_secboot_falcon_run - run the falcon that will perform secure boot - * - * This function is to be called after all chip-specific preparations have - * been completed. It will start the falcon to perform secure boot, wait for - * it to halt, and report if an error occurred. - */ -int -nvkm_secboot_falcon_run(struct nvkm_secboot *sb) -{ - struct nvkm_device *device = sb->subdev.device; - int ret; - - /* Start falcon */ - nvkm_wr32(device, sb->base + 0x100, 0x2); - - /* Wait for falcon halt */ - ret = nvkm_wait_msec(device, 100, sb->base + 0x100, 0x10, 0x10); - if (ret < 0) - return ret; - - /* If mailbox register contains an error code, then ACR has failed */ - ret = nvkm_rd32(device, sb->base + 0x040); - if (ret) { - nvkm_error(&sb->subdev, "ACR boot failed, ret 0x%08x", ret); - falcon_clear_halt_interrupt(device, sb->base); - return -EINVAL; - } - - return 0; -} - - /** * nvkm_secboot_reset() - reset specified falcon */ @@ -202,8 +70,15 @@ static int nvkm_secboot_oneinit(struct nvkm_subdev *subdev) { struct nvkm_secboot *sb = nvkm_secboot(subdev); + struct nvkm_falcon *falcon; int ret = 0; + falcon = nvkm_falcon_get(subdev, sb->func->boot_falcon); + if (IS_ERR(falcon)) + return PTR_ERR(falcon); + sb->debug = falcon->debug; + nvkm_falcon_put(falcon); + /* Call chip-specific init function */ if (sb->func->init) ret = sb->func->init(sb); @@ -257,20 +132,9 @@ nvkm_secboot_ctor(const struct nvkm_secboot_func *func, nvkm_subdev_ctor(&nvkm_secboot, device, index, &sb->subdev); sb->func = func; - /* setup the performing falcon's base address and masks */ - switch (func->boot_falcon) { - case NVKM_FALCON_PMU: - sb->devidx = NVKM_SUBDEV_PMU; - sb->base = 0x10a000; - break; - default: - nvkm_error(&sb->subdev, "invalid secure boot falcon\n"); - return -EINVAL; - }; - nvkm_debug(&sb->subdev, "securely managed falcons:\n"); for_each_set_bit(fid, &sb->func->managed_falcons, NVKM_FALCON_END) - nvkm_debug(&sb->subdev, "- %s\n", managed_falcons_names[fid]); + nvkm_debug(&sb->subdev, "- %s\n", nvkm_falcon_name[fid]); return 0; } diff --git a/drm/nouveau/nvkm/subdev/secboot/gm200.c b/drm/nouveau/nvkm/subdev/secboot/gm200.c index 718cfa129a82..b82e8072e332 100644 --- a/drm/nouveau/nvkm/subdev/secboot/gm200.c +++ b/drm/nouveau/nvkm/subdev/secboot/gm200.c @@ -878,7 +878,7 @@ gm200_secboot_hsf_patch_signature(struct gm200_secboot *gsb, void *acr_image) u32 sig_size; /* Falcon in debug or production mode? */ - if ((nvkm_rd32(sb->subdev.device, sb->base + 0xc08) >> 20) & 0x1) { + if (sb->debug) { sig = acr_image + fw_hdr->sig_dbg_offset; sig_size = fw_hdr->sig_dbg_size; } else { @@ -1092,96 +1092,33 @@ gm200_secboot_blobs_ready(struct gm200_secboot *gsb) * gm200_secboot_load_hs_bl() - load HS bootloader into DMEM and IMEM */ static void -gm200_secboot_load_hs_bl(struct gm200_secboot *gsb, void *data, u32 data_size) +gm200_secboot_load_hs_bl(struct gm200_secboot *gsb, struct nvkm_falcon *falcon, + void *data, u32 data_size) { - struct nvkm_device *device = gsb->base.subdev.device; struct fw_bin_header *hdr = gsb->hsbl_blob; struct fw_bl_desc *hsbl_desc = gsb->hsbl_blob + hdr->header_offset; void *blob_data = gsb->hsbl_blob + hdr->data_offset; void *hsbl_code = blob_data + hsbl_desc->code_off; void *hsbl_data = blob_data + hsbl_desc->data_off; u32 code_size = ALIGN(hsbl_desc->code_size, 256); - const u32 base = gsb->base.base; - u32 blk; u32 tag; - int i; /* * Copy HS bootloader data */ - nvkm_wr32(device, base + 0x1c0, (0x00000000 | (0x1 << 24))); - for (i = 0; i < hsbl_desc->data_size / 4; i++) - nvkm_wr32(device, base + 0x1c4, ((u32 *)hsbl_data)[i]); + nvkm_falcon_load_dmem(falcon, hsbl_data, 0x0, hsbl_desc->data_size, 0); /* * Copy HS bootloader interface structure where the HS descriptor * expects it to be */ - nvkm_wr32(device, base + 0x1c0, - (hsbl_desc->dmem_load_off | (0x1 << 24))); - for (i = 0; i < data_size / 4; i++) - nvkm_wr32(device, base + 0x1c4, ((u32 *)data)[i]); + nvkm_falcon_load_dmem(falcon, data, hsbl_desc->dmem_load_off, data_size, + 0); /* Copy HS bootloader code to end of IMEM */ - blk = (nvkm_rd32(device, base + 0x108) & 0x1ff) - (code_size >> 8); tag = hsbl_desc->start_tag; - nvkm_wr32(device, base + 0x180, ((blk & 0xff) << 8) | (0x1 << 24)); - for (i = 0; i < code_size / 4; i++) { - /* write new tag every 256B */ - if ((i & 0x3f) == 0) { - nvkm_wr32(device, base + 0x188, tag & 0xffff); - tag++; - } - nvkm_wr32(device, base + 0x184, ((u32 *)hsbl_code)[i]); - } - nvkm_wr32(device, base + 0x188, 0); -} - -/** - * gm200_secboot_setup_falcon() - set up the secure falcon for secure boot - */ -static int -gm200_secboot_setup_falcon(struct gm200_secboot *gsb) -{ - struct nvkm_device *device = gsb->base.subdev.device; - struct fw_bin_header *hdr = gsb->hsbl_blob; - struct fw_bl_desc *hsbl_desc = gsb->hsbl_blob + hdr->header_offset; - /* virtual start address for boot vector */ - u32 virt_addr = hsbl_desc->start_tag << 8; - const u32 base = gsb->base.base; - const u32 reg_base = base + 0xe00; - u32 inst_loc; - int ret; - - ret = nvkm_secboot_falcon_reset(&gsb->base); - if (ret) - return ret; - - /* setup apertures - virtual */ - nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_UCODE), 0x4); - nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_VIRT), 0x0); - /* setup apertures - physical */ - nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_PHYS_VID), 0x4); - nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_PHYS_SYS_COH), - 0x4 | 0x1); - nvkm_wr32(device, reg_base + 4 * (FALCON_DMAIDX_PHYS_SYS_NCOH), - 0x4 | 0x2); - - /* Set context */ - if (nvkm_memory_target(gsb->inst->memory) == NVKM_MEM_TARGET_VRAM) - inst_loc = 0x0; /* FB */ - else - inst_loc = 0x3; /* Non-coherent sysmem */ - - nvkm_mask(device, base + 0x048, 0x1, 0x1); - nvkm_wr32(device, base + 0x480, - ((gsb->inst->addr >> 12) & 0xfffffff) | - (inst_loc << 28) | (1 << 30)); - - /* Set boot vector to code's starting virtual address */ - nvkm_wr32(device, base + 0x104, virt_addr); - - return 0; + nvkm_falcon_load_imem(falcon, hsbl_code, falcon->code.limit - code_size, + code_size, tag, 0, false); } /** @@ -1191,16 +1128,27 @@ static int gm200_secboot_run_hs_blob(struct gm200_secboot *gsb, struct nvkm_gpuobj *blob, struct gm200_flcn_bl_desc *desc) { + struct nvkm_subdev *subdev = &gsb->base.subdev; + struct fw_bin_header *hdr = gsb->hsbl_blob; + struct fw_bl_desc *hsbl_desc = gsb->hsbl_blob + hdr->header_offset; struct nvkm_vma vma; + struct nvkm_falcon *falcon; u64 vma_addr; const u32 bl_desc_size = gsb->func->bl_desc_size; + const u32 virt_addr = hsbl_desc->start_tag << 8; u8 bl_desc[bl_desc_size]; int ret; + falcon = nvkm_falcon_get(subdev, gsb->base.func->boot_falcon); + if (IS_ERR(falcon)) + return PTR_ERR(falcon); + /* Map the HS firmware so the HS bootloader can see it */ ret = nvkm_gpuobj_map(blob, gsb->vm, NV_MEM_ACCESS_RW, &vma); - if (ret) + if (ret) { + nvkm_falcon_put(falcon); return ret; + } /* Add the mapping address to the DMA bases */ vma_addr = flcn64_to_u64(desc->code_dma_base) + vma.offset; @@ -1213,19 +1161,28 @@ gm200_secboot_run_hs_blob(struct gm200_secboot *gsb, struct nvkm_gpuobj *blob, /* Fixup the BL header */ gsb->func->fixup_bl_desc(desc, &bl_desc); - /* Reset the falcon and make it ready to run the HS bootloader */ - ret = gm200_secboot_setup_falcon(gsb); - if (ret) - goto done; + /* Reset and set the falcon up */ + nvkm_falcon_reset(falcon); + nvkm_falcon_bind_context(falcon, gsb->inst); /* Load the HS bootloader into the falcon's IMEM/DMEM */ - gm200_secboot_load_hs_bl(gsb, &bl_desc, bl_desc_size); + gm200_secboot_load_hs_bl(gsb, falcon, &bl_desc, bl_desc_size); /* Start the HS bootloader */ - ret = nvkm_secboot_falcon_run(&gsb->base); + nvkm_falcon_set_start_addr(falcon, virt_addr); + nvkm_falcon_start(falcon); + ret = nvkm_falcon_wait_for_halt(falcon, 100); if (ret) goto done; + /* If mailbox register contains an error code, then ACR has failed */ + ret = nvkm_falcon_rd32(falcon, 0x040); + if (ret) { + nvkm_error(subdev, "ACR boot failed, ret 0x%08x", ret); + ret = -EINVAL; + goto done; + } + done: /* Restore the original DMA addresses */ vma_addr = flcn64_to_u64(desc->code_dma_base) - vma.offset; @@ -1237,6 +1194,7 @@ done: /* We don't need the ACR firmware anymore */ nvkm_gpuobj_unmap(&vma); + nvkm_falcon_put(falcon); return ret; } diff --git a/drm/nouveau/nvkm/subdev/secboot/priv.h b/drm/nouveau/nvkm/subdev/secboot/priv.h index f77b69219b44..2123539a7ae5 100644 --- a/drm/nouveau/nvkm/subdev/secboot/priv.h +++ b/drm/nouveau/nvkm/subdev/secboot/priv.h @@ -42,8 +42,6 @@ struct nvkm_secboot_func { int nvkm_secboot_ctor(const struct nvkm_secboot_func *, struct nvkm_device *, int index, struct nvkm_secboot *); -int nvkm_secboot_falcon_reset(struct nvkm_secboot *); -int nvkm_secboot_falcon_run(struct nvkm_secboot *); struct flcn_u64 { u32 lo; -- git-series 0.8.10
Alexandre Courbot
2016-Dec-06 05:35 UTC
[Nouveau] [PATCH 6/8] gr/gf100: split gf100_gr_init_ctxctl()
gf100_gr_init_ctxctl() is basically two different functions (one for use of internal firmware, the other for use of external firmware), but its current layout makes it look more complex than it is. Split it to better reflect that fact. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/nvkm/engine/gr/gf100.c | 212 ++++++++++++++++-------------- 1 file changed, 115 insertions(+), 97 deletions(-) diff --git a/drm/nouveau/nvkm/engine/gr/gf100.c b/drm/nouveau/nvkm/engine/gr/gf100.c index b8095ca89352..71b19f4cebe9 100644 --- a/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1449,134 +1449,139 @@ gf100_gr_init_csdata(struct gf100_gr *gr, nvkm_wr32(device, falcon + 0x01c4, star + 4); } -int -gf100_gr_init_ctxctl(struct gf100_gr *gr) +/* Initialize context from an external (secure or not) firmware */ +static int +gf100_gr_init_ctxctl_ext(struct gf100_gr *gr) { - const struct gf100_grctx_func *grctx = gr->func->grctx; struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_secboot *sb = device->secboot; - int i; int ret = 0; - if (gr->firmware) { - /* load fuc microcode */ - nvkm_mc_unk260(device, 0); - - /* securely-managed falcons must be reset using secure boot */ - if (nvkm_secboot_is_managed(sb, NVKM_FALCON_FECS)) - ret = nvkm_secboot_reset(sb, NVKM_FALCON_FECS); - else - gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c, - &gr->fuc409d); - if (ret) - return ret; + /* load fuc microcode */ + nvkm_mc_unk260(device, 0); - if (nvkm_secboot_is_managed(sb, NVKM_FALCON_GPCCS)) - ret = nvkm_secboot_reset(sb, NVKM_FALCON_GPCCS); - else - gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac, - &gr->fuc41ad); - if (ret) - return ret; + /* securely-managed falcons must be reset using secure boot */ + if (nvkm_secboot_is_managed(sb, NVKM_FALCON_FECS)) + ret = nvkm_secboot_reset(sb, NVKM_FALCON_FECS); + else + gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c, &gr->fuc409d); + if (ret) + return ret; - nvkm_mc_unk260(device, 1); - - /* start both of them running */ - nvkm_wr32(device, 0x409840, 0xffffffff); - nvkm_wr32(device, 0x41a10c, 0x00000000); - nvkm_wr32(device, 0x40910c, 0x00000000); - - if (nvkm_secboot_is_managed(sb, NVKM_FALCON_GPCCS)) - nvkm_secboot_start(sb, NVKM_FALCON_GPCCS); - else - nvkm_wr32(device, 0x41a100, 0x00000002); - if (nvkm_secboot_is_managed(sb, NVKM_FALCON_FECS)) - nvkm_secboot_start(sb, NVKM_FALCON_FECS); - else - nvkm_wr32(device, 0x409100, 0x00000002); - if (nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x409800) & 0x00000001) - break; - ) < 0) - return -EBUSY; + if (nvkm_secboot_is_managed(sb, NVKM_FALCON_GPCCS)) + ret = nvkm_secboot_reset(sb, NVKM_FALCON_GPCCS); + else + gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac, &gr->fuc41ad); + if (ret) + return ret; - nvkm_wr32(device, 0x409840, 0xffffffff); - nvkm_wr32(device, 0x409500, 0x7fffffff); - nvkm_wr32(device, 0x409504, 0x00000021); + nvkm_mc_unk260(device, 1); + + /* start both of them running */ + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x41a10c, 0x00000000); + nvkm_wr32(device, 0x40910c, 0x00000000); - nvkm_wr32(device, 0x409840, 0xffffffff); - nvkm_wr32(device, 0x409500, 0x00000000); - nvkm_wr32(device, 0x409504, 0x00000010); + if (nvkm_secboot_is_managed(sb, NVKM_FALCON_GPCCS)) + nvkm_secboot_start(sb, NVKM_FALCON_GPCCS); + else + nvkm_wr32(device, 0x41a100, 0x00000002); + if (nvkm_secboot_is_managed(sb, NVKM_FALCON_FECS)) + nvkm_secboot_start(sb, NVKM_FALCON_FECS); + else + nvkm_wr32(device, 0x409100, 0x00000002); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800) & 0x00000001) + break; + ) < 0) + return -EBUSY; + + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409500, 0x7fffffff); + nvkm_wr32(device, 0x409504, 0x00000021); + + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409500, 0x00000000); + nvkm_wr32(device, 0x409504, 0x00000010); + if (nvkm_msec(device, 2000, + if ((gr->size = nvkm_rd32(device, 0x409800))) + break; + ) < 0) + return -EBUSY; + + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409500, 0x00000000); + nvkm_wr32(device, 0x409504, 0x00000016); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800)) + break; + ) < 0) + return -EBUSY; + + nvkm_wr32(device, 0x409840, 0xffffffff); + nvkm_wr32(device, 0x409500, 0x00000000); + nvkm_wr32(device, 0x409504, 0x00000025); + if (nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x409800)) + break; + ) < 0) + return -EBUSY; + + if (device->chipset >= 0xe0) { + nvkm_wr32(device, 0x409800, 0x00000000); + nvkm_wr32(device, 0x409500, 0x00000001); + nvkm_wr32(device, 0x409504, 0x00000030); if (nvkm_msec(device, 2000, - if ((gr->size = nvkm_rd32(device, 0x409800))) + if (nvkm_rd32(device, 0x409800)) break; ) < 0) return -EBUSY; - nvkm_wr32(device, 0x409840, 0xffffffff); - nvkm_wr32(device, 0x409500, 0x00000000); - nvkm_wr32(device, 0x409504, 0x00000016); + nvkm_wr32(device, 0x409810, 0xb00095c8); + nvkm_wr32(device, 0x409800, 0x00000000); + nvkm_wr32(device, 0x409500, 0x00000001); + nvkm_wr32(device, 0x409504, 0x00000031); if (nvkm_msec(device, 2000, if (nvkm_rd32(device, 0x409800)) break; ) < 0) return -EBUSY; - nvkm_wr32(device, 0x409840, 0xffffffff); - nvkm_wr32(device, 0x409500, 0x00000000); - nvkm_wr32(device, 0x409504, 0x00000025); + nvkm_wr32(device, 0x409810, 0x00080420); + nvkm_wr32(device, 0x409800, 0x00000000); + nvkm_wr32(device, 0x409500, 0x00000001); + nvkm_wr32(device, 0x409504, 0x00000032); if (nvkm_msec(device, 2000, if (nvkm_rd32(device, 0x409800)) break; ) < 0) return -EBUSY; - if (device->chipset >= 0xe0) { - nvkm_wr32(device, 0x409800, 0x00000000); - nvkm_wr32(device, 0x409500, 0x00000001); - nvkm_wr32(device, 0x409504, 0x00000030); - if (nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x409800)) - break; - ) < 0) - return -EBUSY; - - nvkm_wr32(device, 0x409810, 0xb00095c8); - nvkm_wr32(device, 0x409800, 0x00000000); - nvkm_wr32(device, 0x409500, 0x00000001); - nvkm_wr32(device, 0x409504, 0x00000031); - if (nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x409800)) - break; - ) < 0) - return -EBUSY; - - nvkm_wr32(device, 0x409810, 0x00080420); - nvkm_wr32(device, 0x409800, 0x00000000); - nvkm_wr32(device, 0x409500, 0x00000001); - nvkm_wr32(device, 0x409504, 0x00000032); - if (nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x409800)) - break; - ) < 0) - return -EBUSY; + nvkm_wr32(device, 0x409614, 0x00000070); + nvkm_wr32(device, 0x409614, 0x00000770); + nvkm_wr32(device, 0x40802c, 0x00000001); + } - nvkm_wr32(device, 0x409614, 0x00000070); - nvkm_wr32(device, 0x409614, 0x00000770); - nvkm_wr32(device, 0x40802c, 0x00000001); + if (gr->data == NULL) { + int ret = gf100_grctx_generate(gr); + if (ret) { + nvkm_error(subdev, "failed to construct context\n"); + return ret; } + } - if (gr->data == NULL) { - int ret = gf100_grctx_generate(gr); - if (ret) { - nvkm_error(subdev, "failed to construct context\n"); - return ret; - } - } + return 0; +} + +static int +gf100_gr_init_ctxctl_int(struct gf100_gr *gr) +{ + const struct gf100_grctx_func *grctx = gr->func->grctx; + struct nvkm_subdev *subdev = &gr->base.engine.subdev; + struct nvkm_device *device = subdev->device; + int i; - return 0; - } else if (!gr->func->fecs.ucode) { return -ENOSYS; } @@ -1636,6 +1641,19 @@ gf100_gr_init_ctxctl(struct gf100_gr *gr) return 0; } +int +gf100_gr_init_ctxctl(struct gf100_gr *gr) +{ + int ret; + + if (gr->firmware) + ret = gf100_gr_init_ctxctl_ext(gr); + else + ret = gf100_gr_init_ctxctl_int(gr); + + return ret; +} + static int gf100_gr_oneinit(struct nvkm_gr *base) { -- git-series 0.8.10
Alexandre Courbot
2016-Dec-06 05:35 UTC
[Nouveau] [PATCH 7/8] gr/gf100: use falcon library
Use the falcon library functions in GR instead of poking registers directly. Ideally GR should keep the FECS and GPCCS falcons for as long as it is running, but the lack of a proper fini() function makes this difficult. For now we keep the falcons for the call of gf100_gr_init_ctxctl(). Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/nvkm/engine/gr/gf100.c | 72 +++++++++---------------------- drm/nouveau/nvkm/engine/gr/gf100.h | 2 +- 2 files changed, 25 insertions(+), 49 deletions(-) diff --git a/drm/nouveau/nvkm/engine/gr/gf100.c b/drm/nouveau/nvkm/engine/gr/gf100.c index 71b19f4cebe9..036aaeadcea7 100644 --- a/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drm/nouveau/nvkm/engine/gr/gf100.c @@ -1385,26 +1385,11 @@ gf100_gr_intr(struct nvkm_gr *base) } static void -gf100_gr_init_fw(struct gf100_gr *gr, u32 fuc_base, +gf100_gr_init_fw(struct nvkm_falcon *falcon, struct gf100_gr_fuc *code, struct gf100_gr_fuc *data) { - struct nvkm_device *device = gr->base.engine.subdev.device; - int i; - - nvkm_wr32(device, fuc_base + 0x01c0, 0x01000000); - for (i = 0; i < data->size / 4; i++) - nvkm_wr32(device, fuc_base + 0x01c4, data->data[i]); - - nvkm_wr32(device, fuc_base + 0x0180, 0x01000000); - for (i = 0; i < code->size / 4; i++) { - if ((i & 0x3f) == 0) - nvkm_wr32(device, fuc_base + 0x0188, i >> 6); - nvkm_wr32(device, fuc_base + 0x0184, code->data[i]); - } - - /* code must be padded to 0x40 words */ - for (; i & 0x3f; i++) - nvkm_wr32(device, fuc_base + 0x0184, 0); + nvkm_falcon_load_dmem(falcon, data->data, 0x0, data->size, 0); + nvkm_falcon_load_imem(falcon, code->data, 0x0, code->size, 0, 0, false); } static void @@ -1465,14 +1450,14 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr) if (nvkm_secboot_is_managed(sb, NVKM_FALCON_FECS)) ret = nvkm_secboot_reset(sb, NVKM_FALCON_FECS); else - gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c, &gr->fuc409d); + gf100_gr_init_fw(gr->fecs, &gr->fuc409c, &gr->fuc409d); if (ret) return ret; if (nvkm_secboot_is_managed(sb, NVKM_FALCON_GPCCS)) ret = nvkm_secboot_reset(sb, NVKM_FALCON_GPCCS); else - gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac, &gr->fuc41ad); + gf100_gr_init_fw(gr->gpccs, &gr->fuc41ac, &gr->fuc41ad); if (ret) return ret; @@ -1483,14 +1468,9 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr) nvkm_wr32(device, 0x41a10c, 0x00000000); nvkm_wr32(device, 0x40910c, 0x00000000); - if (nvkm_secboot_is_managed(sb, NVKM_FALCON_GPCCS)) - nvkm_secboot_start(sb, NVKM_FALCON_GPCCS); - else - nvkm_wr32(device, 0x41a100, 0x00000002); - if (nvkm_secboot_is_managed(sb, NVKM_FALCON_FECS)) - nvkm_secboot_start(sb, NVKM_FALCON_FECS); - else - nvkm_wr32(device, 0x409100, 0x00000002); + nvkm_falcon_start(gr->gpccs); + nvkm_falcon_start(gr->fecs); + if (nvkm_msec(device, 2000, if (nvkm_rd32(device, 0x409800) & 0x00000001) break; @@ -1580,7 +1560,6 @@ gf100_gr_init_ctxctl_int(struct gf100_gr *gr) const struct gf100_grctx_func *grctx = gr->func->grctx; struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; - int i; if (!gr->func->fecs.ucode) { return -ENOSYS; @@ -1588,28 +1567,16 @@ gf100_gr_init_ctxctl_int(struct gf100_gr *gr) /* load HUB microcode */ nvkm_mc_unk260(device, 0); - nvkm_wr32(device, 0x4091c0, 0x01000000); - for (i = 0; i < gr->func->fecs.ucode->data.size / 4; i++) - nvkm_wr32(device, 0x4091c4, gr->func->fecs.ucode->data.data[i]); - - nvkm_wr32(device, 0x409180, 0x01000000); - for (i = 0; i < gr->func->fecs.ucode->code.size / 4; i++) { - if ((i & 0x3f) == 0) - nvkm_wr32(device, 0x409188, i >> 6); - nvkm_wr32(device, 0x409184, gr->func->fecs.ucode->code.data[i]); - } + nvkm_falcon_load_dmem(gr->fecs, gr->func->fecs.ucode->data.data, 0x0, + gr->func->fecs.ucode->data.size, 0); + nvkm_falcon_load_imem(gr->fecs, gr->func->fecs.ucode->code.data, 0x0, + gr->func->fecs.ucode->code.size, 0, 0, false); /* load GPC microcode */ - nvkm_wr32(device, 0x41a1c0, 0x01000000); - for (i = 0; i < gr->func->gpccs.ucode->data.size / 4; i++) - nvkm_wr32(device, 0x41a1c4, gr->func->gpccs.ucode->data.data[i]); - - nvkm_wr32(device, 0x41a180, 0x01000000); - for (i = 0; i < gr->func->gpccs.ucode->code.size / 4; i++) { - if ((i & 0x3f) == 0) - nvkm_wr32(device, 0x41a188, i >> 6); - nvkm_wr32(device, 0x41a184, gr->func->gpccs.ucode->code.data[i]); - } + nvkm_falcon_load_dmem(gr->gpccs, gr->func->gpccs.ucode->data.data, 0x0, + gr->func->gpccs.ucode->data.size, 0); + nvkm_falcon_load_imem(gr->gpccs, gr->func->gpccs.ucode->code.data, 0x0, + gr->func->gpccs.ucode->code.size, 0, 0, false); nvkm_mc_unk260(device, 1); /* load register lists */ @@ -1644,13 +1611,20 @@ gf100_gr_init_ctxctl_int(struct gf100_gr *gr) int gf100_gr_init_ctxctl(struct gf100_gr *gr) { + struct nvkm_subdev *subdev = &gr->base.engine.subdev; int ret; + gr->fecs = nvkm_falcon_get(subdev, NVKM_FALCON_FECS); + gr->gpccs = nvkm_falcon_get(subdev, NVKM_FALCON_GPCCS); + if (gr->firmware) ret = gf100_gr_init_ctxctl_ext(gr); else ret = gf100_gr_init_ctxctl_int(gr); + nvkm_falcon_put(gr->gpccs); + nvkm_falcon_put(gr->fecs); + return ret; } diff --git a/drm/nouveau/nvkm/engine/gr/gf100.h b/drm/nouveau/nvkm/engine/gr/gf100.h index 268b8d60ff73..5f484398021d 100644 --- a/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drm/nouveau/nvkm/engine/gr/gf100.h @@ -75,6 +75,8 @@ struct gf100_gr { const struct gf100_gr_func *func; struct nvkm_gr base; + struct nvkm_falcon *fecs; + struct nvkm_falcon *gpccs; struct gf100_gr_fuc fuc409c; struct gf100_gr_fuc fuc409d; struct gf100_gr_fuc fuc41ac; -- git-series 0.8.10
Alexandre Courbot
2016-Dec-06 05:35 UTC
[Nouveau] [PATCH 8/8] secboot: remove nvkm_secboot_start()
Since GR has moved to using the falcon library to start the falcons, this function is not needed anymore. Signed-off-by: Alexandre Courbot <acourbot at nvidia.com> --- drm/nouveau/include/nvkm/subdev/secboot.h | 1 +- drm/nouveau/nvkm/subdev/secboot/base.c | 15 +-------------- drm/nouveau/nvkm/subdev/secboot/gm200.c | 25 +------------------------ drm/nouveau/nvkm/subdev/secboot/gm20b.c | 1 +- drm/nouveau/nvkm/subdev/secboot/priv.h | 1 +- 5 files changed, 0 insertions(+), 43 deletions(-) diff --git a/drm/nouveau/include/nvkm/subdev/secboot.h b/drm/nouveau/include/nvkm/subdev/secboot.h index 7ead4cab363b..905c76a29393 100644 --- a/drm/nouveau/include/nvkm/subdev/secboot.h +++ b/drm/nouveau/include/nvkm/subdev/secboot.h @@ -41,7 +41,6 @@ struct nvkm_secboot { bool nvkm_secboot_is_managed(struct nvkm_secboot *, enum nvkm_falconidx); int nvkm_secboot_reset(struct nvkm_secboot *, u32 falcon); -int nvkm_secboot_start(struct nvkm_secboot *, u32 falcon); int gm200_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); int gm20b_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); diff --git a/drm/nouveau/nvkm/subdev/secboot/base.c b/drm/nouveau/nvkm/subdev/secboot/base.c index bf23349e1edd..65a240ba237c 100644 --- a/drm/nouveau/nvkm/subdev/secboot/base.c +++ b/drm/nouveau/nvkm/subdev/secboot/base.c @@ -40,21 +40,6 @@ nvkm_secboot_reset(struct nvkm_secboot *sb, u32 falcon) } /** - * nvkm_secboot_start() - start specified falcon - */ -int -nvkm_secboot_start(struct nvkm_secboot *sb, u32 falcon) -{ - /* Unmanaged falcon? */ - if (!(BIT(falcon) & sb->func->managed_falcons)) { - nvkm_error(&sb->subdev, "cannot start unmanaged falcon!\n"); - return -EINVAL; - } - - return sb->func->start(sb, falcon); -} - -/** * nvkm_secboot_is_managed() - check whether a given falcon is securely-managed */ bool diff --git a/drm/nouveau/nvkm/subdev/secboot/gm200.c b/drm/nouveau/nvkm/subdev/secboot/gm200.c index b82e8072e332..ea935e15357f 100644 --- a/drm/nouveau/nvkm/subdev/secboot/gm200.c +++ b/drm/nouveau/nvkm/subdev/secboot/gm200.c @@ -1248,30 +1248,6 @@ end: return 0; } -int -gm200_secboot_start(struct nvkm_secboot *sb, enum nvkm_falconidx falcon) -{ - struct gm200_secboot *gsb = gm200_secboot(sb); - int base; - - switch (falcon) { - case NVKM_FALCON_FECS: - base = 0x409000; - break; - case NVKM_FALCON_GPCCS: - base = 0x41a000; - break; - default: - nvkm_error(&sb->subdev, "cannot start unhandled falcon!\n"); - return -EINVAL; - } - - nvkm_wr32(sb->subdev.device, base + 0x130, 0x00000002); - gsb->falcon_state[falcon] = RUNNING; - - return 0; -} - int @@ -1357,7 +1333,6 @@ gm200_secboot = { .init = gm200_secboot_init, .fini = gm200_secboot_fini, .reset = gm200_secboot_reset, - .start = gm200_secboot_start, .managed_falcons = BIT(NVKM_FALCON_FECS) | BIT(NVKM_FALCON_GPCCS), .boot_falcon = NVKM_FALCON_PMU, diff --git a/drm/nouveau/nvkm/subdev/secboot/gm20b.c b/drm/nouveau/nvkm/subdev/secboot/gm20b.c index 66a1d01f45ce..e7cc1e984848 100644 --- a/drm/nouveau/nvkm/subdev/secboot/gm20b.c +++ b/drm/nouveau/nvkm/subdev/secboot/gm20b.c @@ -191,7 +191,6 @@ gm20b_secboot = { .dtor = gm200_secboot_dtor, .init = gm20b_secboot_init, .reset = gm200_secboot_reset, - .start = gm200_secboot_start, .managed_falcons = BIT(NVKM_FALCON_FECS), .boot_falcon = NVKM_FALCON_PMU, }; diff --git a/drm/nouveau/nvkm/subdev/secboot/priv.h b/drm/nouveau/nvkm/subdev/secboot/priv.h index 2123539a7ae5..1bd0abea0843 100644 --- a/drm/nouveau/nvkm/subdev/secboot/priv.h +++ b/drm/nouveau/nvkm/subdev/secboot/priv.h @@ -32,7 +32,6 @@ struct nvkm_secboot_func { int (*fini)(struct nvkm_secboot *, bool suspend); void *(*dtor)(struct nvkm_secboot *); int (*reset)(struct nvkm_secboot *, enum nvkm_falconidx); - int (*start)(struct nvkm_secboot *, enum nvkm_falconidx); /* ID of the falcon that will perform secure boot */ enum nvkm_falconidx boot_falcon; -- git-series 0.8.10
Alexandre Courbot
2016-Dec-06 06:09 UTC
[Nouveau] [PATCH 3/8] core: add falcon library functions
Oops, realized I made a last minute mistake - the following should be squashed into this patch for proper behavior when secure boot is used. Sorry for the inconvenience. diff --git a/drm/nouveau/nvkm/falcon/base.c b/drm/nouveau/nvkm/falcon/base.c index efef9fc63407..75663bd1f650 100644 --- a/drm/nouveau/nvkm/falcon/base.c +++ b/drm/nouveau/nvkm/falcon/base.c @@ -103,10 +103,7 @@ nvkm_falcon_get(const struct nvkm_subdev *subdev, enum nvkm_falconidx id) reg = nvkm_rd32(device, falcon->addr + 0xc08); falcon->debug = (reg >> 20) & 0x1; - if (falcon->secret == 0) - falcon->func = &nvkm_falcon_v1_func; - else - falcon->func = &nvkm_falcon_v1_secure_func; + falcon->func = &nvkm_falcon_v1_func; list_add(&falcon->head, &device->falcons); } else if (falcon->subdev) { diff --git a/drm/nouveau/nvkm/falcon/falcon_v1.c b/drm/nouveau/nvkm/falcon/falcon_v1.c index 25a791f0fb9a..ae6a6098e098 100644 --- a/drm/nouveau/nvkm/falcon/falcon_v1.c +++ b/drm/nouveau/nvkm/falcon/falcon_v1.c @@ -115,12 +115,6 @@ nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *falcon, u32 start_addr) static void nvkm_falcon_v1_start(struct nvkm_falcon *falcon) { - nvkm_falcon_wr32(falcon, 0x100, 0x2); -} - -static void -nvkm_falcon_v1_secure_start(struct nvkm_falcon *falcon) -{ u32 reg = nvkm_falcon_rd32(falcon, 0x100); if (reg & BIT(6)) @@ -197,16 +191,3 @@ nvkm_falcon_v1_func = { .disable = nvkm_falcon_v1_disable, .set_start_addr = nvkm_falcon_v1_set_start_addr, }; - -const struct nvkm_falcon_func -nvkm_falcon_v1_secure_func = { - .load_imem = nvkm_falcon_v1_load_imem, - .load_dmem = nvkm_falcon_v1_load_dmem, - .read_dmem = nvkm_falcon_v1_read_dmem, - .bind_context = nvkm_falcon_v1_bind_context, - .start = nvkm_falcon_v1_secure_start, - .wait_for_halt = nvkm_falcon_v1_wait_for_halt, - .enable = nvkm_falcon_v1_enable, - .disable = nvkm_falcon_v1_disable, - .set_start_addr = nvkm_falcon_v1_set_start_addr, -}; diff --git a/drm/nouveau/nvkm/falcon/priv.h b/drm/nouveau/nvkm/falcon/priv.h index f30729f14ad3..347dc61a8a41 100644 --- a/drm/nouveau/nvkm/falcon/priv.h +++ b/drm/nouveau/nvkm/falcon/priv.h @@ -26,6 +26,5 @@ #include <engine/falcon.h> extern const struct nvkm_falcon_func nvkm_falcon_v1_func; -extern const struct nvkm_falcon_func nvkm_falcon_v1_secure_func; #endif