├── utils └── gru │ ├── Makefile │ ├── README │ ├── info.h │ ├── gru.h │ ├── hw_context.h │ ├── command.h │ ├── info.c │ ├── command.c │ └── console.c ├── patch ├── 0002-add-pci-io-access-cap-for-ubuntu-4.4.0-75-generic.diff └── 0001-Added-legacy-endpoint-type-to-sriov-for-ubuntu-4.4.0-75-generic.diff ├── LICENSE ├── drv ├── gim_dma.h ├── gim_unwrapper.h ├── gim_kcl_type.h ├── gim_fb.h ├── gim_config.h ├── gim_timer.h ├── Makefile ├── gim_flr.h ├── gim_kcl_os.h ├── gim_os_service.h ├── gim_s7150_reg.h ├── gim_gpuiov.h ├── gim_kcl_pci.c ├── gim_pci_config.h ├── gim_kcl_pci.h ├── gim_atombios.h ├── gim_reset.h ├── gim_kcl_os.c ├── gim_os_service.c ├── gim_debug.h ├── gim_interface.h ├── gim_timer.c ├── gim_monitor_ioctl.h ├── gim_irqmgr.h ├── gim_drv.c ├── gim_pci.h ├── gim_pci.c ├── gim_gpuiov.c ├── gim_dma.c ├── gim_monitor_tonga.h ├── gim_fb.c ├── gim_flr.c ├── gim_config.c └── gim_unwrapper.c ├── gim.sh ├── Makefile ├── README.md └── docs ├── gim_runtime_configuration └── environment_setup /utils/gru/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | RM = rm -f 3 | CCFLAGS = -w 4 | 5 | EXEEXT = 6 | EXECUTABLES = gru$(EXEEXT) 7 | 8 | OBJECTS = console.o command.o info.o hw_context.o 9 | 10 | LDLIBS = -lreadline 11 | 12 | all: $(OBJECTS) $(EXECUTABLES) 13 | 14 | .c.o: 15 | $(CC) $(CCFLAGS) -c $< 16 | 17 | gru$(EXEEXT): $(OBJECTS) 18 | $(CC) $(CCFLAGS) -o $(EXECUTABLES) $(OBJECTS) $(LDLIBS) 19 | 20 | clean: 21 | $(RM) $(OBJECTS) $(EXECUTABLES) 22 | -------------------------------------------------------------------------------- /utils/gru/README: -------------------------------------------------------------------------------- 1 | DEPENDENCY: 2 | GNU Readline library. Before build, please make sure this library has been 3 | installed in your build system. It can be downloaded from link: 4 | https://tiswww.case.edu/php/chet/readline/rltop.html 5 | 6 | HOT TO BUILD AND RUN: 7 | GRU build is very easy, just go to source code, then run “make”. A new binary 8 | named “gru” will be in the folder. 9 | To run GRU, just run “./gru” without any additional arguments. Note, GRU need 10 | be run with root permission. 11 | -------------------------------------------------------------------------------- /patch/0002-add-pci-io-access-cap-for-ubuntu-4.4.0-75-generic.diff: -------------------------------------------------------------------------------- 1 | --- linux-4.4.0/drivers/vfio/pci/vfio_pci_config.c 2017-05-02 18:08:22.768271583 +0800 2 | +++ ../linux-4.4.0/drivers/vfio/pci/vfio_pci_config.c 2017-04-25 16:06:24.642099564 +0800 3 | @@ -482,7 +482,7 @@ static int vfio_basic_config_read(struct 4 | u16 cmd = le16_to_cpu(*(__le16 *)&vdev->vconfig[PCI_COMMAND]); 5 | u32 tmp_val = le32_to_cpu(*val); 6 | 7 | - tmp_val |= cmd & PCI_COMMAND_MEMORY; 8 | + tmp_val |= cmd & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO); 9 | *val = cpu_to_le32(tmp_val); 10 | } 11 | 12 | -------------------------------------------------------------------------------- /patch/0001-Added-legacy-endpoint-type-to-sriov-for-ubuntu-4.4.0-75-generic.diff: -------------------------------------------------------------------------------- 1 | --- ./linux-4.4.0/drivers/pci/iov.c 2017-04-26 18:35:14.060299368 +0800 2 | +++ ../linux-4.4.0/drivers/pci/iov.c 2017-04-25 16:03:55.258100666 +0800 3 | @@ -388,7 +388,8 @@ static int sriov_init(struct pci_dev *de 4 | struct pci_dev *pdev; 5 | 6 | if (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_END && 7 | - pci_pcie_type(dev) != PCI_EXP_TYPE_ENDPOINT) 8 | + pci_pcie_type(dev) != PCI_EXP_TYPE_ENDPOINT && 9 | + pci_pcie_type(dev) != PCI_EXP_TYPE_LEG_END) 10 | return -ENODEV; 11 | 12 | pci_read_config_word(dev, pos + PCI_SRIOV_CTRL, &ctrl); 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT license 2 | 3 | Copyright (c) 2014-2019 Advanced Micro Devices, Inc. All rights reserved. 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE 21 | -------------------------------------------------------------------------------- /drv/gim_dma.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__DMA_H 24 | #define _GPU_IOV_MODULE__DMA_H 25 | 26 | #include "gim_adapter.h" 27 | 28 | int dma_clear(struct adapter *adpater, unsigned long long offset, 29 | unsigned long long size); 30 | #endif 31 | -------------------------------------------------------------------------------- /drv/gim_unwrapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__UNWRAPPER_H 24 | #define _GPU_IOV_MODULE__UNWRAPPER_H 25 | 26 | 27 | uint32_t call_interface_functions(const void *buf, size_t count); 28 | uint32_t respond_interface_functions(char *buf); 29 | 30 | #endif 31 | 32 | -------------------------------------------------------------------------------- /utils/gru/info.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017~2018 Advanced Micro Devices, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 | * OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | #ifndef INFO_H_INCLUDED 25 | #define INFO_H_INCLUDED 26 | 27 | typedef struct message_entry { 28 | char *command; 29 | char **message; 30 | } message_entry_t; 31 | 32 | extern message_entry_t gru_message_box[]; 33 | extern message_entry_t gpu_message_box[]; 34 | extern message_entry_t vf_message_box[]; 35 | extern void print_info(char **info); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /drv/gim_kcl_type.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__KCL_TYPE_H 24 | #define _GPU_IOV_MODULE__KCL_TYPE_H 25 | 26 | typedef long kcl_type_size_signed; 27 | typedef unsigned long kcl_type_offset; 28 | typedef unsigned char kcl_type_u8; 29 | typedef unsigned short kcl_type_u16; 30 | typedef unsigned int kcl_type_u32; 31 | typedef unsigned long long kcl_type_u64; 32 | typedef void * kcl_pci_dev_handle; 33 | #endif /* __KCL_TYPE_H__ */ 34 | 35 | -------------------------------------------------------------------------------- /drv/gim_fb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__FB_H 24 | #define _GPU_IOV_MODULE__FB_H 25 | 26 | #include "gim_kcl_type.h" 27 | 28 | struct adapter; 29 | struct function; 30 | 31 | struct slot { 32 | kcl_type_u64 base; 33 | kcl_type_u64 size; 34 | }; 35 | 36 | struct partition { 37 | struct slot slot; 38 | uint32_t occupied; 39 | }; 40 | 41 | void init_vf_fb(struct adapter *, struct function *); 42 | int get_fb_size_static(struct adapter *adapter, u32 *num_vf, u64 base, 43 | u64 total_size, u64 min_size); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /drv/gim_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__CONFIG_H 24 | #define _GPU_IOV_MODULE__CONFIG_H 25 | 26 | int init_config(void); 27 | int save_config(void); 28 | 29 | unsigned int get_fb_partition_option(void); 30 | unsigned int get_scheduler_option(void); 31 | unsigned int get_vf_number_option(void); 32 | unsigned int get_pf_fb_option(void); 33 | unsigned int get_vf_fb_option(void); 34 | unsigned int set_option(int index, int value); 35 | unsigned int get_sched_interval_option(void); 36 | unsigned int get_sched_interval_us_option(void); 37 | unsigned int get_fb_clear_option(void); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /utils/gru/gru.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017~2018 Advanced Micro Devices, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 | * OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | #ifndef GRU_H_INCLUDED 25 | #define GRU_H_INCLUDED 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include 39 | #include 40 | 41 | #define GRU_LOG(msg, args...) \ 42 | printf("\t" msg "\n", ##args); 43 | 44 | #define BDF_STRLEN 8 45 | 46 | /* return values */ 47 | #define RET_ERROR -1 48 | #define RET_OK 0 49 | #define RET_EXIT 1 50 | #define RET_RESTART 2 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /gim.sh: -------------------------------------------------------------------------------- 1 | # !/bin/sh 2 | 3 | # Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE 22 | 23 | ORIGIN_USER=$(whoami) 24 | echo "Current User is $ORIGIN_USER" 25 | 26 | SRC_ROOT=$(cd `dirname $0`; pwd) 27 | 28 | if [ $UID -ne 0 ]; then 29 | echo "Superuser privileges are required to run this script." 30 | cd $SRC_ROOT 31 | su -c './gim.sh' 32 | else 33 | Path=$(readlink /lib/modules/$(uname -r)/build) 34 | echo "check: $Path" 35 | 36 | #A work around for relative Path link for CentOS kernel 4.9 37 | if [ $Path == "../../../usr/src/kernels/4.9.13-22.el7.x86_64" ]; then 38 | cd /lib/modules/$(uname -r)/ 39 | rm ./build 40 | ln -s /usr/src/kernels/4.9.13-22.el7.x86_64 build 41 | ls -l 42 | fi 43 | 44 | #su $(ORIGIN_USER) 45 | 46 | cd $SRC_ROOT/drv 47 | 48 | make 49 | make install 50 | 51 | fi 52 | 53 | exit 54 | -------------------------------------------------------------------------------- /utils/gru/hw_context.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017~2018 Advanced Micro Devices, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 | * OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | #ifndef HW_CONTEXT_H_INCLUDED 25 | #define HW_CONTEXT_H_INCLUDED 26 | #include "gru.h" 27 | #include 28 | 29 | extern int detect_device(void); 30 | extern void show_gpubios(void); 31 | extern void show_gpuinfo(void); 32 | extern void show_gpuvs(void); 33 | extern int open_gpu(char *bus_id); 34 | extern int close_gpu(void); 35 | extern void gpu_status(void); 36 | extern void list_vf(void); 37 | extern void get_vf(char *fb_start, char *fb_size, char *gfx_partition); 38 | extern int release_vf(char *bus_id); 39 | extern int open_vf(char *bus_id); 40 | extern int close_vf(void); 41 | extern char *get_current_gpu(void); 42 | extern char *get_current_vf(void); 43 | extern bool is_gpu_opened(void); 44 | extern bool is_vf_opened(void); 45 | #endif 46 | -------------------------------------------------------------------------------- /drv/gim_timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__TIMER_H 24 | 25 | #define _GPU_IOV_MODULE__TIMER_H 26 | 27 | #define MS_TO_NS(x) (x * 1000000L) 28 | #define US_TO_NS(x) (x * 1000L) 29 | 30 | int set_timeout_timer(struct hrtimer *timer); 31 | int set_timer(struct hrtimer *timer); 32 | void delete_timer(struct hrtimer *timer); 33 | int start_timer(struct hrtimer *timer, int delay_in_ms); 34 | int restart_timer(struct hrtimer *timer); 35 | 36 | #ifdef CONFIG_GIM_HEARTBEAT_TIMER 37 | extern int in_trigger_world_switch; 38 | extern int in_world_switch; 39 | 40 | int start_heartbeat_timer(int delay_in_sec); 41 | void delete_heartbeat_timer(void); 42 | int init_heartbeat_timer(void); 43 | #endif 44 | extern uint32_t complete_time[8]; 45 | 46 | 47 | #define TRACE_SCHED_BUG 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /drv/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE 21 | 22 | obj-m := gim.o 23 | gim-objs := gim_drv.o gim_interface.o gim_adapter.o gim_pci.o gim_unwrapper.o gim_gpuiov.o gim_config.o gim_timer.o gim_fb.o gim_debug.o gim_flr.o gim_atom.o gim_atombios.o gim_os_service.o gim_irqmgr.o gim_kcl_os.o gim_pci_config.o gim_kcl_pci.o gim_reset.o gim_dma.o gim_monitor.o gim_monitor_ioctl.o gim_monitor_tonga.o 24 | 25 | LINUXINCLUDE := $(LINUXINCLUDE) -I$(src)/asic_reg 26 | 27 | #GIM configuration 28 | #ccflags-y += -DCONFIG_GIM_HEARTBEAT_TIMER 29 | #ccflags-y += -D DRV_VERSION=1.0 30 | #ccflags-y += -DCONFIG_MMIO_QEMU_SECURITY 31 | 32 | PWD := $(shell pwd) 33 | 34 | ifeq ($(KERNELRELEASE),) 35 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 36 | 37 | $(info $(KBUILD_CFLAGS)) 38 | all: 39 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 40 | 41 | clean: 42 | $(MAKE) -C $(KERNELDIR) M=$(PWD) clean 43 | 44 | install: 45 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install 46 | endif 47 | -------------------------------------------------------------------------------- /drv/gim_flr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__FLR_H 24 | 25 | #define _GPU_IOV_MODULE__FLR_H 26 | 27 | /* For VF, save and restore the first 1024 Bytes pci cfg space 28 | * For PF, save and restore the first 1280 Bytes pci cfg space 29 | */ 30 | #define VF_FLR_PCI_CONFIG_SIZE 1024 31 | #define PF_FLR_PCI_CONFIG_SIZE 1280 32 | #define PCI_CONFIG_SIZE_TO_SAVE 4096 33 | 34 | struct flr_state { 35 | unsigned int pcie_strap_misc; 36 | unsigned int swrst_ep_control_0; 37 | unsigned int config_memsize; 38 | unsigned char pci_cfg[VF_FLR_PCI_CONFIG_SIZE]; 39 | }; 40 | 41 | int gim_save_cpc_state(struct adapter *adapt, unsigned int *cp_cpc_ic); 42 | int gim_restore_cpc_state(struct adapter *adapt, unsigned int *cp_cpc_ic); 43 | int gim_save_vddgfx_state(struct adapter *adapt, struct function *vf); 44 | int gim_vf_flr(struct adapter *adapt, struct function *vf); 45 | int gim_function_level_reset(struct adapter *adapt, struct function *vf); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | # THE SOFTWARE 21 | 22 | GIM_VERSION=1.1.4 23 | 24 | LINUXINCLUDE := $(LINUXINCLUDE) -I$(src)/drv/asic_reg 25 | KBUILD_CFLAGS := $(KBUILD_CFLAGS) -D DRV_VERSION=$(GIM_VERSION) 26 | 27 | #KBUILD_CFLAGS += -DCONFIG_GIM_HEARTBEAT_TIMER=y 28 | #KBUILD_CFLAGS += -DCONFIG_MMIO_QEMU_SECURITY=y 29 | 30 | obj-m += gim.o 31 | gim-objs := drv/gim_drv.o drv/gim_interface.o drv/gim_adapter.o drv/gim_pci.o drv/gim_unwrapper.o drv/gim_gpuiov.o drv/gim_config.o drv/gim_timer.o drv/gim_fb.o drv/gim_debug.o drv/gim_flr.o drv/gim_atom.o drv/gim_atombios.o drv/gim_os_service.o drv/gim_irqmgr.o drv/gim_kcl_os.o drv/gim_pci_config.o drv/gim_kcl_pci.o drv/gim_reset.o drv/gim_dma.o drv/gim_monitor.o drv/gim_monitor_ioctl.o drv/gim_monitor_tonga.o 32 | 33 | PWD := $(shell pwd) 34 | 35 | ifeq ($(KERNELRELEASE),) 36 | KERNELDIR ?= /lib/modules/$(shell uname -r)/build 37 | 38 | $(info $(KBUILD_CFLAGS)) 39 | all: 40 | $(MAKE) -C $(KERNELDIR) M=$(PWD) modules 41 | 42 | clean: 43 | $(MAKE) -C $(KERNELDIR) M=$(PWD) clean 44 | endif 45 | 46 | -------------------------------------------------------------------------------- /utils/gru/command.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017~2018 Advanced Micro Devices, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 | * OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | #ifndef COMMAND_H_INCLUDED 25 | #define COMMAND_H_INCLUDED 26 | 27 | /* cmd structure */ 28 | typedef struct cmd_entry { 29 | char *command; 30 | int (*pAction) (char *tail); 31 | } cmd_entry_t; 32 | 33 | extern int cmd_gru_help(char *param); 34 | extern int cmd_gru_list(char *param); 35 | extern int cmd_gru_status(char *param); 36 | extern int cmd_gru_bios(char *param); 37 | extern int cmd_gru_open(char *param); 38 | extern int cmd_gru_quit(); 39 | 40 | extern int cmd_gpu_help(char *param); 41 | extern int cmd_gpu_list(char *param); 42 | extern int cmd_gpu_get(char *param); 43 | extern int cmd_gpu_release(char *param); 44 | extern int cmd_gpu_status(char *param); 45 | extern int cmd_gpu_reset(char *param); 46 | extern int cmd_gpu_open(char *param); 47 | extern int cmd_gpu_exit(char *param); 48 | 49 | extern int cmd_vf_help(char *param); 50 | extern int cmd_vf_status(char *param); 51 | extern int cmd_vf_clear(char *param); 52 | extern int cmd_vf_reset(char *param); 53 | extern int cmd_vf_exit(char *param); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /drv/gim_kcl_os.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__KCL_OS_H 24 | #define _GPU_IOV_MODULE__KCL_OS_H 25 | 26 | #include 27 | 28 | #include "gim_kcl_type.h" 29 | 30 | #define PAGE_CNT_UP(x) (((x) + (PAGE_SIZE - 1)) / PAGE_SIZE) 31 | 32 | void kcl_memset(void *s, int c, kcl_type_u64 count); 33 | void *kcl_mem_small_buffer_alloc(kcl_type_u32 size); 34 | void kcl_mem_small_buffer_free(void *p); 35 | void *kcl_mem_alloc_page(void); 36 | void kcl_mem_free_page(void *p); 37 | void *kcl_mem_alloc_page_size(unsigned int page_count); 38 | void *kcl_mem_map_page_list(unsigned long *pagelist, unsigned int count); 39 | unsigned long long kcl_map_page(struct pci_dev *pci_dev, unsigned long p); 40 | void kcl_mem_unmap(void *addr); 41 | unsigned long long kcl_get_page_ma(unsigned long p); 42 | unsigned long long kcl_virt_to_pa(unsigned int *p); 43 | void kcl_reserve_page(void *p); 44 | void kcl_unreserve_page(void *p); 45 | void kcl_get_page(void *p); 46 | void kcl_put_page(void *p); 47 | void kcl_schedule_work(struct work_struct *work); 48 | signed long kcl_thread_sleep(int msecs); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /drv/gim_os_service.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__OS_SERVICE_H 24 | #define _GPU_IOV_MODULE__OS_SERVICE_H 25 | 26 | #include 27 | 28 | #define REG_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT 29 | #define REG_FIELD_MASK(reg, field) reg##__##field##_MASK 30 | 31 | #define REG_SET_FIELD(orig_val, reg, field, field_val) \ 32 | (((orig_val) & ~REG_FIELD_MASK(reg, field)) | \ 33 | (REG_FIELD_MASK(reg, field) & \ 34 | ((field_val) << REG_FIELD_SHIFT(reg, field)))) 35 | 36 | #define REG_GET_FIELD(value, reg, field) \ 37 | (((value) & REG_FIELD_MASK(reg, \ 38 | field)) >> REG_FIELD_SHIFT(reg, field)) 39 | 40 | void map_mmio(struct function *func, struct pci_dev *pdev); 41 | uint32_t read_register(struct function *func, uint32_t index); 42 | void write_register(struct function *func, uint32_t index, uint32_t value); 43 | uint32_t pf_read_register(struct adapter *adapt, uint32_t index); 44 | void pf_write_register(struct adapter *adapt, uint32_t index, uint32_t value); 45 | void delay_in_micro_seconds(uint32_t micro_seconds); 46 | void write_reg32_idx(uint32_t *mmr, uint32_t reg, uint32_t val); 47 | void write_reg32(uint32_t *mmr, uint32_t reg, uint32_t val); 48 | uint32_t read_reg32_idx(uint32_t *mmr, uint32_t reg); 49 | uint32_t read_reg32(uint32_t *mmr, uint32_t reg); 50 | 51 | #endif 52 | 53 | -------------------------------------------------------------------------------- /drv/gim_s7150_reg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__S7150_REG_H 24 | #define _GPU_IOV_MODULE__S7150_REG_H 25 | 26 | #include "gmc/gmc_8_1_d.h" 27 | #include "gmc/gmc_8_1_sh_mask.h" 28 | 29 | #include "bif/bif_5_0_d.h" 30 | #include "bif/bif_5_0_sh_mask.h" 31 | 32 | #include "oss/oss_3_0_d.h" 33 | #include "oss/oss_3_0_sh_mask.h" 34 | 35 | #include "gca/gfx_8_0_d.h" 36 | #include "gca/gfx_8_0_sh_mask.h" 37 | 38 | #include "smu/smu_7_1_2_d.h" 39 | #include "smu/smu_7_1_2_sh_mask.h" 40 | 41 | #define ixCG_INTERRUPT_STATUS 0xC0200048 42 | 43 | #define CG_INTERRUPT_STATUS__DISP_TIMER2_TRIGGER_MASK_MASK 0x00000400L 44 | #define CG_INTERRUPT_STATUS__DISP_TIMER_TRIGGER_MASK_MASK 0x00000800L 45 | 46 | #define CG_INTERRUPT_STATUS__DISP_TIMER2_TRIGGER_MASK__SHIFT 10 47 | #define CG_INTERRUPT_STATUS__DISP_TIMER_TRIGGER_MASK__SHIFT 11 48 | 49 | #define SRBM_STATUS__DRM_RQ_PENDING_MASK 0x00000001L 50 | #define SRBM_STATUS__DRM_BUSY_MASK 0x00040000L 51 | 52 | #define ixSWRST_EP_CONTROL_0 0x140010C 53 | 54 | #define ixSMC_PC_A 0x80000358 55 | #define ixSMC_PC_F 0x8000035C 56 | #define ixSMC_PC_D 0x80000360 57 | #define ixSMC_PC_X 0x80000364 58 | #define ixSMC_PC_M 0x80000368 59 | #define ixSMC_PC_W 0x8000036C 60 | #define ixSMC_PC_C 0x80000370 61 | 62 | #define mmSMU_ACTIVE_FCN_ID 0x01C2 63 | 64 | #define mmCP_DMA_PIO_CONTROL 0xC063 65 | #define mmCP_DMA_PIO_SRC_ADDR 0xC064 66 | #define mmCP_DMA_PIO_SRC_ADDR_HI 0xC065 67 | #define mmCP_DMA_PIO_DST_ADDR 0xC066 68 | #define mmCP_DMA_PIO_DST_ADDR_HI 0xC067 69 | #define mmCP_DMA_PIO_COMMAND 0xC0E8 70 | 71 | #define mmCC_BIF_BX_STRAP0 0x14e1 72 | 73 | #endif /* __S7150_REG_H__ */ 74 | 75 | -------------------------------------------------------------------------------- /drv/gim_gpuiov.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__GPUIOV_H 24 | #define _GPU_IOV_MODULE__GPUIOV_H 25 | 26 | #define PF_ID(x) (x) 27 | #define VF_ID(x) (0x80 | x) 28 | #define CMD_EXECUTE 0x10 29 | #define CMD_EXECUTE_INTR_EN 0x20 30 | #define PCI_CFG_SPACE_SIZE 256 31 | #define PCI_CFG_SPACE_EXP_SIZE 4096 32 | 33 | enum gpu_iov_command { 34 | IDLE_GPU = 0x01, 35 | SAVE_GPU_STATE = 0x02, 36 | LOAD_GPU_STATE = 0x03, 37 | RUN_GPU = 0x04, 38 | CONTEXT_SWITCH = 0x05, 39 | ENABLE_AUTO_HW_SWITCH = 0x06, 40 | INIT_GPU = 0x07, 41 | SAVE_RLCV_STATE = 0x08, 42 | LOAD_RLCV_STATE = 0x09 43 | }; 44 | 45 | enum gpu_iov_command_status { 46 | COMMAND_DONE = 0x0, 47 | IDLING_GPU = 0x11, 48 | SAVING_GPU_STATE = 0x12, 49 | LOADING_GPU_STATE = 0x13, 50 | ENABLING_GPU = 0x14, 51 | INITING_GPU = 0x15, 52 | SAVING_RLCV_STATE = 0x16, 53 | LOADING_RLCV_STATE = 0x17, 54 | GFX_HANG = 0x0e, 55 | SDMA_HANG = 0x0f 56 | }; 57 | 58 | int pci_gpu_iov_init(struct pci_dev *dev, struct pci_gpu_iov *gpuiov); 59 | int set_gpuiov_context(struct pci_dev *dev, struct pci_gpu_iov *gpuiov, 60 | kcl_type_u8 context_size, kcl_type_u8 context_loc, 61 | kcl_type_u32 context_offset); 62 | int set_gpuiov_function_id(struct pci_dev *dev, struct pci_gpu_iov *gpuiov, 63 | kcl_type_u8 function_id); 64 | int set_gpuiov_next_function_id(struct pci_dev *dev, 65 | struct pci_gpu_iov *gpuiov, kcl_type_u8 next_func_id); 66 | int set_gpuiov_total_fb_consumed(struct pci_dev *dev, 67 | struct pci_gpu_iov *gpuiov, 68 | kcl_type_u16 total_fb_consumed); 69 | int set_gpuiov_vf_frame_buffer(struct pci_dev *dev, struct pci_gpu_iov *gpuiov, 70 | int vf, kcl_type_u16 size, kcl_type_u16 offset); 71 | int set_gpuiov_command(struct pci_dev *dev, struct pci_gpu_iov *gpuiov, 72 | int command, int func_id, int next_func_id); 73 | int get_vf_hw_fb_settings(struct pci_dev *pf_dev, struct pci_gpu_iov *gpuiov, 74 | int vf_id, uint32_t *fb_start, uint32_t *fb_size); 75 | 76 | #endif 77 | 78 | -------------------------------------------------------------------------------- /drv/gim_kcl_pci.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #include 24 | 25 | #include "gim_kcl_pci.h" 26 | #include "gim_debug.h" 27 | #include "gim_interface.h" 28 | 29 | int kcl_pci_read_config_byte( 30 | kcl_pci_dev_handle dev, kcl_type_u16 where, kcl_type_u8 *val_ptr) 31 | { 32 | return pci_read_config_byte((struct pci_dev *)dev, where, val_ptr); 33 | } 34 | 35 | int kcl_pci_read_config_word( 36 | kcl_pci_dev_handle dev, kcl_type_u16 where, kcl_type_u16 *val_ptr) 37 | { 38 | return pci_read_config_word((struct pci_dev *)dev, where, val_ptr); 39 | } 40 | 41 | int kcl_pci_read_config_dword( 42 | kcl_pci_dev_handle dev, kcl_type_u16 where, kcl_type_u32 *val_ptr) 43 | { 44 | return pci_read_config_dword((struct pci_dev *)dev, where, val_ptr); 45 | } 46 | 47 | int kcl_pci_write_config_byte( 48 | kcl_pci_dev_handle dev, kcl_type_u16 where, kcl_type_u8 val) 49 | { 50 | return pci_write_config_byte((struct pci_dev *)dev, where, val); 51 | } 52 | 53 | int kcl_pci_write_config_word( 54 | kcl_pci_dev_handle dev, kcl_type_u16 where, kcl_type_u16 val) 55 | { 56 | return pci_write_config_word((struct pci_dev *)dev, where, val); 57 | } 58 | 59 | int kcl_pci_write_config_dword( 60 | kcl_pci_dev_handle dev, kcl_type_u16 where, kcl_type_u32 val) 61 | { 62 | return pci_write_config_dword((struct pci_dev *)dev, where, val); 63 | } 64 | 65 | void kcl_pci_enable_bus_master(kcl_pci_dev_handle dev) 66 | { 67 | unsigned short cmd = 0; 68 | 69 | kcl_pci_read_config_word(dev, PCI_COMMAND, &cmd); 70 | cmd |= PCI_COMMAND_MASTER; 71 | kcl_pci_write_config_word(dev, PCI_COMMAND, cmd); 72 | } 73 | 74 | void kcl_pci_disable_bus_master(kcl_pci_dev_handle dev) 75 | { 76 | unsigned short cmd = 0; 77 | 78 | kcl_pci_read_config_word(dev, PCI_COMMAND, &cmd); 79 | cmd &= (~PCI_COMMAND_MASTER); 80 | kcl_pci_write_config_word(dev, PCI_COMMAND, cmd); 81 | } 82 | 83 | int kcl_pci_find_capability(kcl_pci_dev_handle dev, 84 | int cap) 85 | { 86 | return pci_find_capability((struct pci_dev *)dev, cap); 87 | } 88 | 89 | int kcl_pci_find_ext_capability(kcl_pci_dev_handle dev, 90 | int cap, int pos) 91 | { 92 | return pci_find_ext_capability(dev, cap); 93 | } 94 | 95 | -------------------------------------------------------------------------------- /drv/gim_pci_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__PCI_CONFIG_H 24 | #define _GPU_IOV_MODULE__PCI_CONFIG_H 25 | 26 | 27 | #include 28 | #include 29 | 30 | #define PCI_EXT_CONFIG_OFFSET 256 31 | #define PCI_EXT_CONFIG_SIZE 4096 32 | #define UNCORR_ERR_STATUS 0x154 33 | #define PCI_EXP 0x58 34 | #define PCI_AER 0x150 /* Advanced Error Reporting */ 35 | #define PCIE_UNCORR_ERR_STATUS 0x154 36 | #define PCIE_UNCORR_ERR_MASK 0x158 37 | #define PCIE_CORR_ERR_STATUS 0x160 38 | #define PCIE_CORR_ERR_MASK 0x164 39 | 40 | 41 | /* 42 | *Note that CAP_SRIOV is defined in the Tonga register spec as 0x330 43 | *but this is not guaranteed across asic generations. 44 | *While this will work with Tonga, it may not work for future asics. 45 | *If future asics place the CAP_SRIOV at a different offset 46 | *then the table will have to be dynamically adjusted for the new offset. 47 | *This value is used as an offset for the statically defined pci tables only. 48 | *Anywhere else in the code that needs to know the SRIOV offset is done 49 | *by scanning through the pci config space for the appropriate section header. 50 | */ 51 | #define CAP_SRIOV 0x330 52 | 53 | struct pci_def { 54 | int offset; 55 | int size; 56 | char *name; 57 | }; 58 | 59 | struct aer_item { 60 | int aer_offset; 61 | struct pci_dev *dev; 62 | }; 63 | 64 | void dump_pci_config(uint8_t *pci_buf, char *comment); 65 | void compare_pci_config(uint8_t *pci_buf, uint8_t *pci_buf2, char *comment); 66 | void pci_config_save(struct pci_dev *dev, uint8_t *buf, int count); 67 | void pci_config_restore(struct pci_dev *dev, uint8_t *buf, int count); 68 | void pci_cache_bridges(struct pci_device_id *dev_list, 69 | int max_size, struct aer_item *aer_list); 70 | void pci_disable_bridge_error_reporting(struct aer_item *aer_list); 71 | void pci_cache_pfs(struct pci_dev *pf_devices[], int pf_count, 72 | int max_bridges, struct aer_item *device_list); 73 | int pci_validate_devices(struct aer_item *device_list); 74 | int pci_check_for_error(struct pci_dev *dev); 75 | void pci_disable_error_reporting(struct pci_dev *dev); 76 | int check_for_error(struct pci_dev *dev, char *comment); 77 | #endif 78 | -------------------------------------------------------------------------------- /drv/gim_kcl_pci.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__KCL_PCI_H 24 | #define _GPU_IOV_MODULE__KCL_PCI_H 25 | 26 | #include "gim_kcl_type.h" 27 | 28 | int kcl_pci_read_config_byte(kcl_pci_dev_handle dev, 29 | kcl_type_u16 where, 30 | kcl_type_u8 * val_ptr); 31 | 32 | int kcl_pci_read_config_word(kcl_pci_dev_handle dev, 33 | kcl_type_u16 where, 34 | kcl_type_u16 *val_ptr); 35 | 36 | int kcl_pci_read_config_dword(kcl_pci_dev_handle dev, 37 | kcl_type_u16 where, 38 | kcl_type_u32 *val_ptr); 39 | 40 | int kcl_pci_write_config_byte(kcl_pci_dev_handle dev, 41 | kcl_type_u16 where, 42 | kcl_type_u8 val); 43 | 44 | int kcl_pci_write_config_word(kcl_pci_dev_handle dev, 45 | kcl_type_u16 where, 46 | kcl_type_u16 val); 47 | 48 | int kcl_pci_write_config_dword(kcl_pci_dev_handle dev, 49 | kcl_type_u16 where, 50 | kcl_type_u32 val); 51 | 52 | void kcl_pci_enable_bus_master(kcl_pci_dev_handle dev); 53 | 54 | void kcl_pci_disable_bus_master(kcl_pci_dev_handle dev); 55 | 56 | int kcl_pci_find_ext_capability(kcl_pci_dev_handle dev, 57 | int cap, int pos); 58 | 59 | int kcl_pci_find_capability(kcl_pci_dev_handle dev, 60 | int cap); 61 | 62 | /* Extended Capabilities (PCI-X 2.0 and Express) */ 63 | #define GIM_PCI_EXT_CAP_ID(header) (header & 0x0000ffff) 64 | #define GIM_PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf) 65 | #define GIM_PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc) 66 | #define GIM_PCI_CFG_SPACE_SIZE 256 67 | #define GIM_PCI_CFG_SPACE_EXP_SIZE 4096 68 | #define GIM_MIN_BYTES_PER_CAP 8 69 | 70 | /* SR-IOV capabiltiy */ 71 | #define PCI_EXT_CAP_ID__SRIOV 0x10 72 | #define PCI_SRIOV_CTRL 0x08/* SR-IOV Control */ 73 | #define PCI_SRIOV_CTRL_VFE 0x01/* VF Enable */ 74 | #define PCI_SRIOV_CTRL_MSE 0x08/* VF Memory Space Enable */ 75 | 76 | #define PCI_CAP_ID_EXP 0x10 /* PCI Express */ 77 | 78 | #define PCI_STATUS 0x06 /* 16 bits */ 79 | #define PCI_REVISION_ID 0x08 /* Revision ID */ 80 | #define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ 81 | #define PCI_CAPABILITY_LIST 0x34 /* Offset of first cap list entry */ 82 | 83 | 84 | #endif /* __KCL_PCI_H__ */ 85 | 86 | -------------------------------------------------------------------------------- /drv/gim_atombios.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__GIM_ATOMBIOS_H 24 | #define _GPU_IOV_MODULE__GIM_ATOMBIOS_H 25 | 26 | #include "gim_adapter.h" 27 | #include "gim_atombios_com.h" 28 | 29 | #define ATOM_DATATABLE 0 30 | #define ATOM_COMMANDTABLE 1 31 | #define ATOM_MASTER_ROM_HEADERTABLE 2 32 | 33 | #define ATOM_ASIC_POSTED 0 34 | #define ATOM_ASIC_NEED_POST 1 35 | 36 | #define ONE_K 0x00000400L 37 | #define HALF_K 0x00000200L 38 | 39 | #define VBIOS_POST_INIT_ASIC 0 40 | #define VBIOS_POST_LOAD_UCODE 1 41 | #define VBIOS_POST_FULL_POST 2 42 | #define VBIOS_POST_REPOST 3 43 | #define VBIOS_POST_UNKNOWN 4 44 | 45 | #define FORCE_VBIOS_POST 10 46 | #define POST_VBIOS_IF_NEEDED 11 47 | 48 | #define UPDATE_FIRMWARE_SMU 0x01 49 | #define UPDATE_FIRMWARE_RLCV 0x02 50 | #define UPDATE_FIRMWARE_TOC 0x04 51 | #define UPDATE_FIRMWARE_SMC_PATCH 0x8 52 | 53 | #define PPSMC_MSG_THERMAL_CNTL_ENABLE (0x10a) 54 | 55 | int atom_init_parser(struct adapter *adapt); 56 | int atom_post_vbios(struct adapter *adapt, int post_type); 57 | int atom_chk_asic_status(struct adapter *adapt); 58 | int patch_firmware(struct adapter *adapt); 59 | 60 | struct cail_parser_table_context { 61 | uint32_t size; 62 | uint32_t table_index; /* indicate index of Command table */ 63 | void *para_ptr; /* Parameter space pointer */ 64 | uint32_t parser_result; /* Save the result from Parser */ 65 | }; 66 | 67 | struct cail_adapter_config_info { 68 | uint32_t rom_length; /* Size of ATI ROM in bytes */ 69 | uint32_t rom_header_offset; /* Offset to ROM header */ 70 | 71 | void *rom_base_addr; /* Mapped logical base addr of ROM */ 72 | void *io_base_addr; /* IO access address */ 73 | 74 | }; 75 | 76 | int atom_dpm_state_cntl(struct adapter *adapt, 77 | struct pwr_mgt_param *param); 78 | 79 | void enable_thermal_control(struct adapter *adapt); 80 | 81 | #define GIM_VBIOS_SIGNATURE "761295520" 82 | #define GIM_VBIOS_SIGNATURE_OFFSET 0x30 83 | #define GIM_VBIOS_SIGNATURE_SIZE sizeof(GIM_VBIOS_SIGNATURE) 84 | #define GIM_VBIOS_SIGNATURE_END (GIM_VBIOS_SIGNATURE_OFFSET \ 85 | + GIM_VBIOS_SIGNATURE_SIZE) 86 | #define GIM_IS_VALID_VBIOS(p) \ 87 | ((p)[0] == 0x55 && (p)[1] == 0xAA) 88 | 89 | #define GIM_VBIOS_LENGTH(p) \ 90 | ((p)[2] << 9) 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /drv/gim_reset.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__RESET_H 24 | #define _GPU_IOV_MODULE__RESET_H 25 | 26 | #define PCI_EXP 0x58 27 | /* #define PCI_EXP_DEVSTA 0x0a */ 28 | 29 | /* Bridge Control Register */ 30 | #define PCI_BRIDGE_CNTL_REG 0x3E 31 | #define PCI_BRIDGE_CNTL_REG__SECONDARY_BUS_RESET 0x00000040 32 | 33 | /* PCIE Link Cap Register */ 34 | #define PCIE_LINK_CAP_OFFSET 0x0C 35 | #define PCIE_LINK_CAP__LINK_SPEED 0x0000000F 36 | #define PCIE_LINK_CAP__LINK_WIDTH_MASK 0x000003f0L 37 | #define PCIE_LINK_CAP__LINK_WIDTH__SHIFT 0x00000004 38 | #define PCIE_LINK_CAP__CLOCK_POWER_MANAGEMENT_MASK 0x00040000 39 | #define PCIE_LINK_CAP__LINK_ACTIVE_REPORT_CAPABLE 0x00100000 40 | 41 | /* PCIE Link Status Register */ 42 | #define PCIE_LINK_STATUS_OFFSET 0x12 43 | #define PCIE_LINK_STATUS__LINK_TRAINING 0x00000800 44 | #define PCIE_LINK_STATUS__LINK_ACTIVE 0x00002000 45 | 46 | 47 | /* PCIE Link Cap 2 Register */ 48 | #define PCIE_LINK_CAP2_OFFSET 0x2C 49 | #define PCIE_LINK_CAP2__SUPPORTED_LINK_SPEEDS_VECTOR_MASK 0x000000FE 50 | #define PCIE_LINK_CAP2__SUPPORTED_LINK_SPEEDS_VECTOR__SHIFT 0x00000001 51 | #define PCIE_LINK_CAP2__SUPPORTED_LINK_SPEEDS_VECTOR__2_5 0x00000001 52 | #define PCIE_LINK_CAP2__SUPPORTED_LINK_SPEEDS_VECTOR__5_0 0x00000002 53 | #define PCIE_LINK_CAP2__SUPPORTED_LINK_SPEEDS_VECTOR__8_0 0x00000004 54 | 55 | 56 | #define PCI_VENDOR_ID 0x00 57 | #define PCI_DEVICE_ID 0x02 58 | 59 | /* 500 ms */ 60 | #define PCIE_TRAINING_TIMEOUT_LIMIT (500*1000) 61 | 62 | /* Extended Capabilities (PCI-X 2.0 and Express) */ 63 | #define PCI_EXT_CAP_ID(header) (header & 0x0000ffff) 64 | #define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf) 65 | #define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc) 66 | 67 | /* Advanced Error Reporting */ 68 | #define PCI_EXT_CAP_ID_AER 1 69 | #define PCI_ERR_UNCOR_STATUS 4 70 | #define PCI_ERR_CORR_STATUS 0x10 71 | #define PCI_ERR_UNCOR_MASK 8/* Uncorrectable Error Mask */ 72 | 73 | #define PCI_CFG_SPACE_SIZE 256 74 | #define PCI_CFG_SPACE_EXP_SIZE 4096 75 | 76 | #define CAP_SRIOV 0x330 77 | #define PCI_SRIOV_CAP 0x04 78 | 79 | #define SOFT_REGISTERS_TABLE_28 0x3fc54 80 | #define FW_STATE_543 0x3d440 81 | #define UCODE_COUNT 13 82 | #define TABLE_SIZE 0x20 83 | #define FW_STATE_684 0x3d674 84 | #define FW_STATE_685 0x3d678 85 | 86 | int gim_pci_hot_reset(struct adapter *adapt); 87 | void gim_clear_all_errors(struct adapter *adapt); 88 | int validate_link_status(struct adapter *adapt); 89 | 90 | #endif /*__RESET_H__*/ 91 | 92 | 93 | -------------------------------------------------------------------------------- /drv/gim_kcl_os.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "gim_kcl_os.h" 33 | #include "gim_debug.h" 34 | 35 | void kcl_memset(void *s, int c, kcl_type_u64 count) 36 | { 37 | memset(s, c, count); 38 | } 39 | 40 | void *kcl_mem_small_buffer_alloc(kcl_type_u32 size) 41 | { 42 | return kmalloc(size, GFP_KERNEL); 43 | } 44 | 45 | void kcl_mem_small_buffer_free(void *p) 46 | { 47 | kfree(p); 48 | } 49 | 50 | void *kcl_mem_alloc_page() 51 | { 52 | return (void *)alloc_page(GFP_KERNEL | __GFP_HIGHMEM); 53 | } 54 | 55 | void kcl_mem_free_page(void *p) 56 | { 57 | __free_page(p); 58 | } 59 | 60 | void *kcl_mem_alloc_page_size(unsigned int page_count) 61 | { 62 | return kmalloc(page_count * PAGE_SIZE, GFP_KERNEL); 63 | } 64 | 65 | void *kcl_mem_map_page_list(unsigned long *pagelist, unsigned int count) 66 | { 67 | void *vaddr = (void *)vmap((struct page **)pagelist, 68 | count, VM_MAP, PAGE_KERNEL); 69 | return vaddr; 70 | } 71 | 72 | unsigned long long kcl_map_page(struct pci_dev *pci_dev, unsigned long p) 73 | { 74 | return pci_map_page(pci_dev, (struct page *)p, 0, 75 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 76 | } 77 | 78 | void kcl_mem_unmap(void *addr) 79 | { 80 | if (addr) 81 | vunmap(addr); 82 | } 83 | 84 | unsigned long long kcl_get_page_ma(unsigned long p) 85 | { 86 | return (unsigned long long)(page_to_pfn((struct page *)p)< 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "gim_debug.h" 32 | #include "gim_adapter.h" 33 | #include "gim_os_service.h" 34 | 35 | void map_mmio(struct function *func, struct pci_dev *pdev) 36 | { 37 | void *p_mmr_base = NULL; 38 | int i = 0; 39 | unsigned int flag = 0; 40 | 41 | /* Find the MMIO BAR. 42 | *The MMIO has the attributes of MEMORY and non-prefetch. 43 | */ 44 | 45 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { 46 | flag = pci_resource_flags(pdev, i); 47 | if ((flag & IORESOURCE_MEM) && !(flag & IORESOURCE_PREFETCH)) 48 | break; 49 | } 50 | 51 | if (i == DEVICE_COUNT_RESOURCE) { 52 | gim_err("adapter has no suitable MMIO region\n"); 53 | return; 54 | } 55 | 56 | p_mmr_base = ioremap_nocache(pci_resource_start(pdev, i), 57 | pci_resource_len(pdev, i)); 58 | 59 | if (p_mmr_base == NULL) { 60 | gim_err("can't iomap for BAR %d\n", i); 61 | return; 62 | } 63 | 64 | func->mmr_base = p_mmr_base; 65 | func->mmr_size = pci_resource_len(pdev, i); 66 | 67 | } 68 | 69 | 70 | 71 | uint32_t read_register(struct function *func, uint32_t index) 72 | { 73 | return read_reg32(func->mmr_base, index); 74 | } 75 | 76 | 77 | 78 | void write_register(struct function *func, uint32_t index, uint32_t value) 79 | { 80 | return write_reg32(func->mmr_base, index, value); 81 | } 82 | 83 | 84 | uint32_t pf_read_register(struct adapter *adapt, uint32_t index) 85 | { 86 | return read_register(&adapt->pf, index); 87 | } 88 | 89 | void pf_write_register(struct adapter *adapt, uint32_t index, uint32_t value) 90 | { 91 | return write_register(&adapt->pf, index, value); 92 | } 93 | 94 | 95 | 96 | void delay_in_micro_seconds(uint32_t micro_seconds) 97 | { 98 | udelay(micro_seconds); 99 | } 100 | 101 | /* 102 | * read_reg32() - Read the MMIO register 103 | * @mmr: start virtual address for MMIO register 104 | * @reg: register offset 105 | * return register val: success 106 | */ 107 | uint32_t read_reg32(uint32_t *mmr, uint32_t reg) 108 | { 109 | uint32_t val; 110 | 111 | val = ioread32((unsigned char *)mmr + (reg << 2)); 112 | return val; 113 | } 114 | 115 | /* 116 | * read_reg32_idx() - Read the MMIO register via MM index/data 117 | * @mmr: start virtual address for MMIO register 118 | * @reg: register offset 119 | * return register val: success 120 | */ 121 | uint32_t read_reg32_idx(uint32_t *mmr, uint32_t reg) 122 | { 123 | 124 | unsigned int val; 125 | 126 | iowrite32(reg << 2, mmr); 127 | val = ioread32((unsigned char *)mmr + 4); 128 | return val; 129 | } 130 | 131 | 132 | /* 133 | * write_reg32() - Write the MMIO register 134 | * @mmr: start virtual address for MMIO register 135 | * @reg: register offset 136 | * @val: value to be write to register 137 | */ 138 | void write_reg32(uint32_t *mmr, uint32_t reg, uint32_t val) 139 | { 140 | iowrite32(val, (unsigned char *)mmr + (reg << 2)); 141 | } 142 | 143 | /* 144 | * write_reg32_idx() - Write the MMIO register via MM index/data 145 | * @mmr: start virtual address for MMIO register 146 | * @reg: register offset 147 | * @val: value to be write to register 148 | */ 149 | 150 | void write_reg32_idx(uint32_t *mmr, uint32_t reg, uint32_t val) 151 | { 152 | iowrite32(reg << 2, mmr); 153 | iowrite32(val, (unsigned char *)mmr + 4); 154 | } 155 | 156 | -------------------------------------------------------------------------------- /drv/gim_debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__DEBUG_H 24 | 25 | #define _GPU_IOV_MODULE__DEBUG_H 26 | 27 | #include "gim_adapter.h" 28 | 29 | #define GIM_LOG_LEVEL_NONE 0 30 | #define GIM_LOG_LEVEL_ERR 1 31 | #define GIM_LOG_LEVEL_WARN 2 32 | #define GIM_LOG_LEVEL_INFO 3 33 | #define GIM_LOG_LEVEL_DEBUG 4 34 | 35 | #define NOTIFY_METHOD_MAILBOX 1 36 | #define NOTIFY_METHOD_MSI 2 37 | #define NOTIFY_METHOD_ALLBITS 3 38 | 39 | 40 | /* written by driver - the combined size */ 41 | #define REGISTER_RESTORE_LIST_SIZE 0x5f 42 | /* currently need 0x28 locations */ 43 | #define REGISTER_LIST_FORMAT_START 0x60 44 | 45 | #define GFX3D_STATIC_START 0x60 46 | #define GFX3D_STATIC_LENGTH 0x61 47 | #define GFX3D_DYN_START 0x62 48 | #define GFX3D_DYN_LENGTH 0x63 49 | #define CMP_STATIC_START 0x64 50 | #define CMP_STATIC_LENGTH 0x65 51 | #define CMP_DYN_START 0x66 52 | #define CMP_DYN_LENGTH 0x67 53 | #define CMN_STATIC_START 0x68 54 | #define CMN_STATIC_LENGTH 0x69 55 | #define CMN_DYN_START 0x6a 56 | #define CMN_DYN_LENGTH 0x6b 57 | #define VDDGFX_START 0x6c 58 | #define VDDGFX_LENGTH 0x6d 59 | /* current length is 37, save 6 more locations (2 more indirect) 60 | * 0x60 to 0x8a -> 43 locations 61 | */ 62 | /* currently 9 entries */ 63 | #define REGISTER_LIST_FORMAT_SEPARATE_START 0x8b 64 | #define VIRT_START 0x8b 65 | #define VIRT_LENGTH 0x8c 66 | /* current length is 9, save 15 more locations (4 more indirect) 67 | * 0x8b - 0x9a 68 | */ 69 | /* this list is constant */ 70 | #define STARTING_OFFSET_START 0x9b 71 | /* contents are relative to RegisterListFormatStart */ 72 | #define GFX3D_INDIRECT_START 0x9b 73 | #define CMP_INDIRECT_START 0x9c 74 | #define CMN_INDIRECT_START 0x9d 75 | #define VDDGFX_INDIRECT_START 0x9e 76 | /* contents are relative to start of virtual list */ 77 | #define VIRT_INDIRECT_START 0x9f 78 | 79 | int gim_get_log_level(void); 80 | 81 | void gim_set_log_level(int level); 82 | 83 | int gim_log_msg(const char *fmt, ...); 84 | 85 | #define gim_info(fmt, s...) \ 86 | do { if (gim_get_log_level() >= GIM_LOG_LEVEL_INFO) \ 87 | printk(KERN_INFO "gim info:(%s:%d) " fmt, __func__, \ 88 | __LINE__, ##s); } while (0) 89 | 90 | #define gim_warn(fmt, s...) \ 91 | do { if (gim_get_log_level() >= GIM_LOG_LEVEL_WARN) \ 92 | printk(KERN_WARNING "gim warning:(%s:%d) " fmt, __func__, \ 93 | __LINE__, ##s); } while (0) 94 | 95 | #define gim_err(fmt, s...) \ 96 | do { if (gim_get_log_level() >= GIM_LOG_LEVEL_ERR) \ 97 | printk(KERN_ERR "gim error:(%s:%d) " fmt, __func__, \ 98 | __LINE__, ##s); } while (0) 99 | 100 | #define gim_dbg(fmt, s...) \ 101 | do { if (gim_get_log_level() >= GIM_LOG_LEVEL_DEBUG) \ 102 | printk(KERN_INFO "gim debug:(%s:%d) " fmt, __func__, \ 103 | __LINE__, ##s); } while (0) 104 | 105 | 106 | void gim_init_debug_interface(void); 107 | 108 | void gim_exit_debug_interface(void); 109 | 110 | void gim_save_register(struct function *func); 111 | bool gim_check_register(struct function *func); 112 | void gim_dump_register(struct function *func); 113 | 114 | char *get_int(int *ret, char *in); 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /drv/gim_interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__GIM_INTERFACE_H 24 | #define _GPU_IOV_MODULE__GIM_INTERFACE_H 25 | 26 | #include "gim_adapter.h" 27 | #include "gim_command.h" 28 | 29 | /* Options */ 30 | #define GIM_OPTION__FB_PARTITION 0 31 | #define GIM_OPTION__FB_PARTITION__FIX_SIZE 0 32 | #define GIM_OPTION__FB_PARTITION__VARIED_SIZE 1 33 | 34 | #define GIM_OPTION__SCHEDULER 1 35 | #define GIM_OPTION__SCHEDULER__ROUND_ROBIN 0 36 | #define GIM_OPTION__SCHEDULER__BORROWED_VIRTUAL_TIME 1 37 | 38 | #define GIM_OPTION__VF_NUMBER 2 39 | #define GIM_OPTION__VF_NUMBER__DEFAULT 0 /* Maximum VFs are enabled. */ 40 | 41 | #define GIM_OPTION__PF_FB_SIZE 3 42 | 43 | /* Min size of FB is allocated to PF. */ 44 | #define GIM_OPTION__PF_FB_SIZE__DEFAULT 0 45 | 46 | /* Max size of FB is allocated to PF. */ 47 | #define GIM_OPTION__PF_FB_SIZE__MAX 65536 48 | 49 | uint32_t set_opt(uint32_t index, uint32_t value); 50 | uint32_t get_opt(uint32_t index); 51 | 52 | /* Multi-adapter management */ 53 | uint32_t get_pf_count(void); 54 | uint32_t enumerate_pfs(uint32_t count, uint32_t *pf_bdfs); 55 | uint32_t enumerate_all_vf_bdfs(uint32_t pf_bdf, 56 | uint32_t count, uint32_t *vf_bdfs); 57 | 58 | /* sriov management */ 59 | uint32_t get_total_vfs(uint32_t pf_bdf); 60 | 61 | uint32_t enable_sriov(uint32_t pf_bdf, uint32_t vfs_count); 62 | uint32_t disable_sriov(uint32_t pf_bdf); 63 | 64 | /* VF management */ 65 | uint32_t get_available_vf_count(uint32_t pf_bdf); 66 | uint32_t enumerate_available_vfs(uint32_t pf_bdf, 67 | uint32_t count, uint32_t *vf_bdfs); 68 | uint32_t vf_alloc(uint32_t vf_bdf); 69 | uint32_t vf_free(uint32_t vf_bdf); 70 | uint32_t set_pid(uint32_t vf_bdf, uint32_t pid); 71 | uint32_t set_fb(uint32_t vf_bdf, uint32_t fb_offset); 72 | uint32_t set_sched_level(uint32_t vf_bdf, uint32_t sched_level); 73 | uint32_t set_acpi_event(uint32_t vf_bdf, uint32_t acpi_event); 74 | uint32_t enumerate_all_vfs(uint32_t pf_bdf, uint32_t count, 75 | struct vf_info *vf_info); 76 | /* FB management */ 77 | uint32_t get_max_fb_slot(uint32_t pf_bdf); 78 | uint32_t fb_alloc(uint32_t pf_bdf, uint32_t fb_size); 79 | uint32_t fb_free(uint32_t pf_bdf, uint32_t fb_offset); 80 | 81 | /* Scheduler */ 82 | uint32_t pause_sched(uint32_t pf_bdf); 83 | uint32_t resume_sched(uint32_t pf_bdf); 84 | uint32_t start_scheduler(uint32_t pf_bdf); 85 | uint32_t get_active_functions(uint32_t pf_bdf); 86 | uint32_t init(uint32_t vf_bdf); 87 | uint32_t idle(uint32_t vf_bdf); 88 | uint32_t save(uint32_t vf_bdf); 89 | uint32_t load(uint32_t vf_bdf); 90 | uint32_t run(uint32_t vf_bdf); 91 | uint32_t context_switch(uint32_t vf_bdf, uint32_t vf_bdf_next); 92 | 93 | void switch_to_self(uint32_t pf_bdf, int enable); 94 | void enable_preemption(uint32_t pf_bdf, int enable); 95 | 96 | uint32_t send_signal(int vm_id, int signal_no); 97 | uint32_t alloc_vf(uint32_t pf_bdf, int dom_id, int qemu_pid, 98 | int fb_size, int sched_level); 99 | uint32_t alloc_vf_from_bdf(uint32_t vf_bdf, int dom_id, 100 | int qemu_pid, int fb_size, int sched_level); 101 | uint32_t free_vf_from_bdf(uint32_t vf_bdf); 102 | 103 | uint32_t free_vf_from_domid(uint32_t domid); 104 | 105 | uint32_t trgger_single_switch(uint32_t pf_bdf); 106 | 107 | uint32_t do_world_switch(uint32_t pf_bdf); 108 | void map_mmr(uint32_t vf_bdf, kcl_type_u64 phys_addr, kcl_type_u64 length); 109 | struct pci_dev *bdf_to_dev(uint32_t bdf); 110 | uint32_t get_pdev_bdf(struct pci_dev *pdev); 111 | struct flr_state *get_flr_state_ptr(uint32_t bdf); 112 | int is_pf(int bdf); 113 | struct adapter *bdf_to_adapter(uint32_t bdf); 114 | void remove_from_run_list(struct function *func); 115 | void switch_to_vf(struct adapter *a, struct function *f); 116 | struct function_list_node *get_function_node(struct function *f); 117 | #endif 118 | 119 | -------------------------------------------------------------------------------- /drv/gim_timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | #include "gim_adapter.h" 35 | #include "gim_timer.h" 36 | #include "gim_debug.h" 37 | #include "gim_command.h" 38 | #include "gim_kcl_os.h" 39 | #include "gim_interface.h" 40 | #include "gim_irqmgr.h" 41 | 42 | enum hrtimer_restart my_timer_callback(struct hrtimer *timer) 43 | { 44 | struct adapter *adapt = container_of(timer, 45 | struct adapter, sched_timer); 46 | 47 | kcl_schedule_work(&adapt->sched_work); 48 | #ifdef CONFIG_GIM_HEARTBEAT_TIMER 49 | adapt->world_switch_count++; 50 | #endif 51 | 52 | return HRTIMER_NORESTART; 53 | } 54 | 55 | enum hrtimer_restart timeout_timer_callback(struct hrtimer *timer) 56 | { 57 | struct adapter *adapt = container_of(timer, struct adapter, 58 | timeout_timer); 59 | 60 | if(handle_fullaccess_timeout(adapt)) 61 | start_timer(&adapt->timeout_timer, 62 | TIMEOUT_CHECK_INTERVAL); 63 | 64 | return HRTIMER_NORESTART; 65 | } 66 | 67 | int set_timeout_timer(struct hrtimer *timer) 68 | { 69 | hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 70 | timer->function = &timeout_timer_callback; 71 | return 0; 72 | } 73 | 74 | int set_timer(struct hrtimer *timer) 75 | { 76 | hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 77 | timer->function = &my_timer_callback; 78 | return 0; 79 | } 80 | 81 | void delete_timer(struct hrtimer *timer) 82 | { 83 | int ret; 84 | 85 | ret = hrtimer_cancel(timer); 86 | } 87 | 88 | int start_timer(struct hrtimer *timer, int delay_in_us) 89 | { 90 | ktime_t ktime = ktime_set(0, US_TO_NS(delay_in_us)); 91 | hrtimer_start(timer, ktime, HRTIMER_MODE_REL); 92 | return 0; 93 | } 94 | 95 | int restart_timer(struct hrtimer *timer) 96 | { 97 | hrtimer_restart(timer); 98 | return 0; 99 | } 100 | 101 | #ifdef CONFIG_GIM_HEARTBEAT_TIMER 102 | /* 103 | * Heartbeat timer provides a useful interval to display debug statistics 104 | * that can be accumulated in a debug version of the GIM driver. 105 | * 106 | * Currently counts the number of scheduler timer ticks and world switches. 107 | * 108 | * This is purely debug code and is controlled by the CONFIG_GIM_HEARTBEAT_TIMER define 109 | */ 110 | 111 | static struct hrtimer heartbeat_timer; 112 | 113 | int start_heartbeat_timer(int delay_in_sec) 114 | { 115 | ktime_t ktime = ktime_set(delay_in_sec, 0); 116 | 117 | hrtimer_start(&heartbeat_timer, ktime, HRTIMER_MODE_REL); 118 | return 0; 119 | } 120 | 121 | void delete_heartbeat_timer(void) 122 | { 123 | delete_timer(&heartbeat_timer); 124 | } 125 | 126 | enum hrtimer_restart my_watchdog_callback(struct hrtimer *timer) 127 | { 128 | int i; 129 | int num_adapters = get_adapter_count(); 130 | struct adapter *adapt = get_adapters(); 131 | int ws_count = 0; 132 | 133 | /* Check if anything running */ 134 | 135 | for (i = 0; i < num_adapters; ++i) { 136 | if (adapt != NULL) 137 | ws_count += adapt->world_switch_count; 138 | } 139 | 140 | if (ws_count) { 141 | 142 | for (i = 0; i < num_adapters; ++i) { 143 | if (adapt != NULL) { 144 | gim_info("GIM Heartbeat - Adp[%d] WS = %d\n", 145 | i, adapt->world_switch_count); 146 | dump_runlist(adapt); 147 | adapt->world_switch_count = 0; 148 | } else { 149 | gim_info("GIM Heartbeat - Adp[%d] = NULL\n", i); 150 | } 151 | ++adapt; 152 | } 153 | } 154 | start_heartbeat_timer(10); 155 | return HRTIMER_NORESTART; 156 | } 157 | 158 | int init_heartbeat_timer(void) 159 | { 160 | hrtimer_init(&heartbeat_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 161 | heartbeat_timer.function = &my_watchdog_callback; 162 | return 0; 163 | } 164 | 165 | #endif 166 | -------------------------------------------------------------------------------- /drv/gim_monitor_ioctl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__MONITOR_IOCTL_H 24 | #define _GPU_IOV_MODULE__MONITOR_IOCTL_H 25 | 26 | #include 27 | #include "gim_adapter.h" 28 | #include "gim_monitor.h" 29 | 30 | #define AMDGIM_SYSFS_ENABLED 31 | #define AMDGIM_DEVFS_ENABLED 32 | 33 | #define GIM_IOCTL_NR(n) _IOC_NR(n) 34 | 35 | struct amdgim_mutex_lock { 36 | bool locked; 37 | struct mutex lock_mutex; 38 | struct timeval timeout_start; 39 | spinlock_t atom_lock; 40 | }; 41 | 42 | struct amdgim_devfs_dev { 43 | struct cdev cdev; 44 | int major; 45 | unsigned char command[AMDGIM_STRLEN_LONG]; 46 | unsigned char result[AMDGIM_BUFFER_SIZE * MAX_ADAPTERS_IN_SYSTEM]; 47 | unsigned int read_offset; 48 | unsigned int result_len; 49 | }; 50 | 51 | enum amdgim_ioctl_index { 52 | AMDGIM_IOCTL_SET_COMMAND, 53 | AMDGIM_IOCTL_GET_RESULT, 54 | AMDGIM_IOCTL_GET_GPU_INFO, 55 | AMDGIM_IOCTL_GET_GPU_VOLATILE_STATE, 56 | AMDGIM_IOCTL_GET_GPU_VBIOS_INFO, 57 | AMDGIM_IOCTL_GET_GPU_VF_INFO, 58 | AMDGIM_IOCTL_GET_VF_DETAIL_INFO, 59 | AMDGIM_IOCTL_INDEX_LEN 60 | }; 61 | 62 | typedef int amdgim_ioctl_func_t(struct file *filp, 63 | unsigned int cmd, unsigned long arg); 64 | 65 | struct amdgim_ioctl { 66 | amdgim_ioctl_func_t *func; 67 | }; 68 | 69 | #define IOCTL_FUNC_ENTRY(f) ((amdgim_ioctl_func_t *)f) 70 | 71 | #ifdef AMDGIM_DEVFS_ENABLED 72 | int amdgim_ioctl_set_command(struct file *filp, unsigned int cmd, 73 | unsigned long arg); 74 | int amdgim_ioctl_get_result(struct file *filp, unsigned int cmd, 75 | unsigned long arg); 76 | int amdgim_ioctl_get_gpu_info(struct file *filp, unsigned int cmd, 77 | unsigned long arg); 78 | int amdgim_ioctl_get_gpu_volatile_state(struct file *filp, unsigned int cmd, 79 | unsigned long arg); 80 | int amdgim_ioctl_get_gpu_vbios_info(struct file *filp, unsigned int cmd, 81 | unsigned long arg); 82 | int amdgim_ioctl_get_gpu_vf_info(struct file *filp, unsigned int cmd, 83 | unsigned long arg); 84 | int amdgim_ioctl_get_vf_detail_info(struct file *filp, unsigned int cmd, 85 | unsigned long arg); 86 | int amdgim_ioctl_get_error_entry(struct file *filp, unsigned int cmd, 87 | unsigned long arg); 88 | 89 | int amdgim_create_cdev(void); 90 | int amdgim_destroy_cdev(void); 91 | #endif 92 | 93 | union amdgim_attr { 94 | struct device_attribute dev_attr; 95 | struct driver_attribute drv_attr; 96 | }; 97 | 98 | struct amdgim_sysfs_dev { 99 | union { 100 | struct device *pdev; 101 | struct device_driver *pdrv; 102 | } node; 103 | union amdgim_attr attr; 104 | char *rbuf; 105 | char *wbuf; 106 | unsigned int rlen; 107 | struct function *owner; 108 | }; 109 | 110 | struct amdgim_sysfs_group { 111 | 112 | struct amdgim_sysfs_dev drv_gpuinfo; 113 | struct amdgim_sysfs_dev drv_gpuvs; 114 | struct amdgim_sysfs_dev drv_gpubios; 115 | 116 | struct amdgim_sysfs_dev 117 | vf_gpuvf[MAX_ADAPTERS_IN_SYSTEM][MAX_VIRTUAL_FUNCTIONS]; 118 | struct amdgim_sysfs_dev 119 | vf_clrvffb[MAX_ADAPTERS_IN_SYSTEM][MAX_VIRTUAL_FUNCTIONS]; 120 | struct amdgim_sysfs_dev 121 | vf_flr[MAX_ADAPTERS_IN_SYSTEM][MAX_VIRTUAL_FUNCTIONS]; 122 | 123 | struct amdgim_sysfs_dev pf_gpuvf[MAX_ADAPTERS_IN_SYSTEM]; 124 | struct amdgim_sysfs_dev pf_getvf[MAX_ADAPTERS_IN_SYSTEM]; 125 | struct amdgim_sysfs_dev pf_relvf[MAX_ADAPTERS_IN_SYSTEM]; 126 | struct amdgim_sysfs_dev pf_hotlink_reset[MAX_ADAPTERS_IN_SYSTEM]; 127 | struct amdgim_mutex_lock sysfs_mutex; 128 | }; 129 | 130 | #ifdef AMDGIM_SYSFS_ENABLED 131 | int amdgim_create_sysfs_dev(struct device_driver *pdrv); 132 | int amdgim_destroy_sysfs_dev(void); 133 | #endif 134 | 135 | struct amdgim_monitor_driver { 136 | struct amdgim_devfs_dev devfs_dev; 137 | struct amdgim_sysfs_group sysfs_group; 138 | struct mutex core_func_mutex; 139 | }; 140 | 141 | struct amdgim_monitor_driver *get_monitor_driver(void); 142 | int amdgim_create_devices(struct device_driver *pdrv); 143 | void amdgim_destroy_devices(void); 144 | 145 | #endif 146 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GIM 2 | 3 | # This repository has been replaced by https://github.com/amd/MxGPU-Virtualization. Please visit the new repository for support with current GPUs. 4 | 5 | ```javascript 6 | Copyright (c) 2014-2019 Advanced Micro Devices, Inc. All rights reserved. 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE 24 | ``` 25 | ## What is GIM? 26 | [GIM](https://github.com/GPUOpen-LibrariesAndSDKs/MxGPU-Virtualization) 27 | (GPU-IOV Module) is a Linux kernel module for AMD SR-IOV based HW 28 | Virtualization (MxGPU) product. It can support KVM, open source Xen and 29 | any other Linux kernel based hypervisors with necessary kernel compatibility 30 | modification. GIM is reponsible for: 31 | * GPU IOV initialization 32 | * Virtual function configuration and enablement 33 | * GPU scheduling for world switch 34 | * Hang detection and virtual function level reset (FLR) 35 | * PF/VF hand shake and other GPU utilities. 36 | 37 | Currently, only AMD S7150 series GPUs are supported. 38 | 39 | ## DOCUMENTATION: 40 | All documents are listed in SRC_ROOT/docs 41 | 42 | ## SOFTWARE REQUIREMENTS: 43 | * The tested host OS for GIM is Ubuntu16.04.2. All other 44 | hypervisor SW(KVM, XEN, QEMU, LIBVIRT) versions are aligned with default 45 | version of OS. 46 | 47 | GIM supports KVM in Ubuntu 16.04, and supports XEN in CentOS 7.3. 48 | 49 | Host OS | Kernel | KVM/Xen | QEMU | libvirt 50 | ------------|-------------------|---------|-------|-------------- 51 | Ubuntu 16.04.2 server | 4.4.0-75-generic | KVM 4.4 | 2.5.0 | 1.3.1 | 52 | 53 | 54 | * The tested guest OS 55 | 56 | Guest OS | Distributions 57 | ----------|------------------------------------------------- 58 | Linux | Ubuntu 16.04 LTS 64bit; CentOS 7.3 64 bit 59 | Windows | Win7 64bit; Win10 TH2 64bit 60 | 61 | 62 | * Some legacy Linux kernels have issues with enabling PCI SR-IOV. 63 | It is suggested to use Ubuntu 4.4.0-75-generic kernel and apply the patch for 64 | IOV module. The patch file can be found under SRC_ROOT/patch. 65 | 66 | ## HOW TO BUILD & INSTALL: 67 | All driver source codes are under SRC_ROOT/drv. 68 | 1. Typing command "make" in terminal under SRC_ROOT/drv can generate gim.ko. 69 | 2. Typing command "make install" in terminal under SRC_ROOT/drv can install 70 | gim.ko to /lib/modules/$(KERNELRELEASE)/GIM/. 71 | 3. Generally, Just run helper SRC_ROOT/gim.sh in a command terminal also can 72 | completed build and installation. And gim.sh -help can display usages. 73 | 4. Blacklist amdgpu and amdkfd and reboot the server. Such as, under Ubuntu, 74 | by adding the following line to the end of file /etc/modprobe.d/blacklist.conf 75 | 76 | ``` 77 | blacklist amdgpu 78 | blacklist amdkfd 79 | ``` 80 | ## HOW TO LOAD: 81 | 1. Typing command "modprobe gim" in terminal can load gim driver 82 | 2. Usually, Typing command "lsmod | grep gim " and "lspci | grep AMD" in 83 | terminal can help to check if gim driver is loaded 84 | 85 | ## HOW TO CONFIGURE BUILD: 86 | Read this section carefully. New configuration options could be added in 87 | each release, and unexpected problems can occur if the configuration files are 88 | not set up as expected. 89 | 90 | * Alternative configuration commands are 91 | 92 | CONFIG_GIM_HEARTBEAT_TIMER 93 | Heartbeat timer provides a useful way to display statistics 94 | of GIM periodically for debug purpose. 95 | Currently, it only counts the number of scheduler timer ticks 96 | and world switches, if the configuration is defined. 97 | 98 | * Edit configuraiton in Makefile 99 | 100 | GIM is an external kernel driver module. The driver configuration is 101 | different from upstream kernel driver. Editing "KBUILD_CFLAGS" in 102 | the Makefile is preferred to pass the configuration to GIM. 103 | 104 | ## HISTORY: 105 | - 1.0 (2017/07/20) 106 | The original release support AMD S7150 series. 107 | 108 | - 2.0 (2018/9/30) 109 | Fix some issues for AMD S7150 series. 110 | 111 | - 3.0 (2019/3/28) 112 | Adding support for mixed guest OS. 113 | Fix some issues for AMD S7150 series. 114 | -------------------------------------------------------------------------------- /drv/gim_irqmgr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__IRQMGR_H 24 | #define _GPU_IOV_MODULE__IRQMGR_H 25 | 26 | #include "gim_adapter.h" 27 | 28 | /* irq source */ 29 | #define IRQ_SOURCEX_BIF_MAILBOX_MSGBUF_VALID 0xFF00018b 30 | #define IRQ_SOURCEX_BIF_MAILBOX_MSGBUF_ACK 0xFF00018c 31 | 32 | /* src_id */ 33 | #define IH_IV_SRCID_BIF_PF_VF_MSGBUF_VALID 0x00000087 /* 135 */ 34 | #define IH_IV_SRCID_BIF_PF_VF_MSGBUF_ACK 0x00000088 /* 136 */ 35 | #define IH_IV_SRCID_BIF_VF_PF_MSGBUF_VALID 0x00000089 /* 137 */ 36 | #define IH_IV_SRCID_BIF_VF_PF_MSGBUF_ACK 0x0000008a /* 138 */ 37 | 38 | /* ext_id */ 39 | #define IV_EXTID_NONE 0x00000000 40 | 41 | #define IVRING_SIZE (1 << 12) 42 | #define IVRING_ENTRY_SIZE 16 43 | #define IVRING_ALIGNMENT 0x00000100 44 | 45 | /* ih doorbell offset */ 46 | #define DOORBELL_IH 0x1E8 47 | 48 | #define IVRING_OVERFLOW_NUM_IRQ_TO_KEEP 32 49 | 50 | #define NO_RESET 0 51 | #define RESET_REQUEST 1 52 | 53 | /* the interval(us) to check if VF full access timeout */ 54 | #define TIMEOUT_CHECK_INTERVAL 100 * 1000 55 | /* timeout(us) */ 56 | #define FULLACCESS_TIMEOUT (5000 * 1000) 57 | 58 | 59 | enum irq_src_idx { 60 | IRQ_SOURCE_MAILBOX_MSGBUF_VALID = 0, 61 | IRQ_SOURCE_MAILBOX_MSGBUF_ACK, 62 | IRQ_SOURCE_MAX_NUMBER 63 | }; 64 | 65 | struct irq_source { 66 | unsigned int irq_src; 67 | /* IV Interrupt source ID */ 68 | unsigned int source_id; 69 | /* IV Interrupt extended ID */ 70 | unsigned int extended_id; 71 | /* Mask register */ 72 | unsigned int mask_reg; 73 | /* Mask bit to enable/disable the interrupt */ 74 | unsigned int mask_bit; 75 | /* Some sources use more than 1 bit for the mask 76 | * Use this to clear out all the bits 77 | */ 78 | unsigned int unmask_bit; 79 | /* Bitmap of all ack bits in the mask register */ 80 | unsigned int mask_reg_ack_bits; 81 | /* Ack register */ 82 | unsigned int ack_reg; 83 | /* Ack bit to acknowledget the interrupt */ 84 | unsigned int ack_bit; 85 | /* Bitmap of all ack bits in the ack register*/ 86 | unsigned int ack_reg_ack_bits; 87 | /* This function could be NULL */ 88 | int (*enable_func)(struct adapter *adapt, 89 | enum irq_src_idx irq_src, unsigned int state); 90 | /* This function could be NULL */ 91 | int (*ack_func)(struct adapter *adapt, enum irq_src_idx irq_src); 92 | }; 93 | 94 | int ih_iv_ring_init(struct adapter *adapt); 95 | void ih_iv_ring_hw_init(struct adapter *adapt); 96 | int ih_iv_ring_fini(struct adapter *adapt); 97 | void ih_iv_ring_enable(struct adapter *adapt); 98 | void ih_iv_ring_disable(struct adapter *adapt); 99 | void ih_iv_ring_setup_wptr(struct adapter *adapt); 100 | void ih_iv_ring_setup_rptr(struct adapter *adapt); 101 | unsigned char ih_iv_ring_get_pointers(struct adapter *adapt, 102 | unsigned int *rptr, 103 | unsigned int *wptr, 104 | unsigned char *over_flow); 105 | void ih_iv_ring_update_rptr(struct adapter *adapt, 106 | unsigned int rptr); 107 | int ih_irq_source_enable(struct adapter *adapt); 108 | int ih_irq_source_disable(struct adapter *adapt); 109 | int ih_irq_process(void *context); 110 | 111 | /* MAILBOX */ 112 | int mailbox_update_index(struct function *func, unsigned int index); 113 | int mailbox_msg_rcv(struct adapter *adapt, int func_id); 114 | int mailbox_msg_trn(struct function *func, unsigned int msg_data); 115 | int mailbox_ack_receipt(struct function *func); 116 | int mailbox_clear_msg_valid(struct function *func); 117 | int mailbox_notify_flr(struct adapter *adapt, unsigned int completion); 118 | 119 | int handle_req_gpu_init_access(struct adapter *adapt, 120 | int func_id, int is_reset); 121 | int handle_rel_gpu_init_access(struct adapter *adapt, int func_id); 122 | int handle_req_gpu_fini_access(struct adapter *adapt, int func_id); 123 | int handle_rel_gpu_fini_access(struct adapter *adapt, int func_id); 124 | int handle_fullaccess_timeout(struct adapter *adapt); 125 | void signal_scheduler(void *pcontext); 126 | #endif /* __IRQMGR_H__ */ 127 | 128 | -------------------------------------------------------------------------------- /drv/gim_drv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "gim_adapter.h" 29 | #include "gim_unwrapper.h" 30 | #include "gim_pci.h" 31 | #include "gim_interface.h" 32 | #include "gim_config.h" 33 | #include "gim_timer.h" 34 | #include "gim_debug.h" 35 | #include 36 | #include 37 | #include "gim_pci_config.h" 38 | #include "gim_monitor_ioctl.h" 39 | 40 | #ifndef DRV_VERSION 41 | #define DRV_VERSION 0.0 42 | #endif 43 | 44 | #define _STR(x) #x 45 | #define STR(x) _STR(x) 46 | 47 | char gim_driver_name[] = "gim"; 48 | char gim_driver_version[] = STR(DRV_VERSION); 49 | static const char gim_driver_string[] = 50 | "GPU IOV MODULE"; 51 | static const char gim_copyright[] = 52 | "Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved."; 53 | 54 | 55 | /* TBD: Tonga Device ID */ 56 | static const struct pci_device_id gim_pci_tbl[] = { 57 | { PCI_VDEVICE(ATI, 0x6929), 0 }, /* Tonga S7150 'Cloudy Quark' */ 58 | /* required last entry */ 59 | {0, } 60 | }; 61 | 62 | 63 | 64 | #define MAX_BRIDGES 10 65 | 66 | struct aer_item device_list[MAX_BRIDGES]; 67 | 68 | static ssize_t sriov_store(struct device_driver *drv, const char *buf, 69 | size_t count) 70 | { 71 | call_interface_functions(buf, count); 72 | return count; 73 | } 74 | 75 | static ssize_t sriov_show(struct device_driver *drv, char *buf) 76 | { 77 | return respond_interface_functions(buf); 78 | } 79 | 80 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) 81 | static DRIVER_ATTR(sriov, (S_IWUSR|S_IRUSR), sriov_show, sriov_store); 82 | #else 83 | static DRIVER_ATTR_RW(sriov); 84 | #endif 85 | 86 | 87 | static int gim_probe(struct pci_dev *pdev, 88 | const struct pci_device_id *ent) 89 | { 90 | set_new_adapter(pdev); 91 | gim_info("AMD GIM probe: pf_count = %d\n", get_adapter_count()); 92 | return 0; 93 | } 94 | 95 | static void gim_remove(struct pci_dev *pdev) 96 | { 97 | gim_info("AMD GIM remvoe\n"); 98 | } 99 | 100 | static void gim_shutdown(struct pci_dev *pdev) 101 | { 102 | gim_info("AMD GIM shutdown\n"); 103 | } 104 | 105 | static pci_ers_result_t gim_io_error_detected(struct pci_dev *pdev, 106 | pci_channel_state_t state) 107 | { 108 | gim_info("AMD GIM io error detected\n"); 109 | 110 | /* Request a slot slot reset. */ 111 | return PCI_ERS_RESULT_NEED_RESET; 112 | } 113 | 114 | static pci_ers_result_t gim_io_slot_reset(struct pci_dev *pdev) 115 | { 116 | gim_info("AMD GIM io slot reset\n"); 117 | return PCI_ERS_RESULT_RECOVERED; 118 | } 119 | 120 | static void gim_io_resume(struct pci_dev *pdev) 121 | { 122 | gim_info("AMD GIM io resume\n"); 123 | 124 | } 125 | 126 | static struct pci_error_handlers gim_err_handler = { 127 | .error_detected = gim_io_error_detected, 128 | .slot_reset = gim_io_slot_reset, 129 | .resume = gim_io_resume, 130 | }; 131 | 132 | static struct pci_driver gim_driver = { 133 | .name = gim_driver_name, 134 | .id_table = NULL, 135 | .probe = gim_probe, 136 | .remove = gim_remove, 137 | .shutdown = gim_shutdown, 138 | .err_handler = &gim_err_handler 139 | }; 140 | 141 | static int gim_init(void) 142 | { 143 | int ret = 0; 144 | int pf_count; 145 | 146 | 147 | struct pci_dev *pfDevices[MAX_ADAPTERS_IN_SYSTEM]; 148 | 149 | gim_info("Start AMD open source GIM initialization\n"); 150 | 151 | gim_info("%s - version %s\n", 152 | gim_driver_string, gim_driver_version); 153 | 154 | gim_info("%s\n", gim_copyright); 155 | init_config(); 156 | 157 | pf_count = enumerate_all_pfs(gim_pci_tbl, 158 | MAX_ADAPTERS_IN_SYSTEM, pfDevices); 159 | if (pf_count > 0) { 160 | int count; 161 | 162 | for (count = 0 ; count < pf_count ; count++) 163 | gim_probe(pfDevices[count], NULL); 164 | 165 | } 166 | 167 | ret = pci_register_driver(&gim_driver); 168 | 169 | ret = driver_create_file(&gim_driver.driver, 170 | &driver_attr_sriov); 171 | 172 | 173 | gim_init_debug_interface(); 174 | 175 | amdgim_create_devices(&gim_driver.driver); 176 | 177 | #ifdef CONFIG_GIM_HEARTBEAT_TIMER 178 | init_heartbeat_timer(); 179 | start_heartbeat_timer(10); /* 10 second delay */ 180 | #endif 181 | 182 | return ret; 183 | } 184 | 185 | static void gim_exit(void) 186 | { 187 | gim_info("Exit AMD open source GIM!\n"); 188 | 189 | idle_all_adapters(); 190 | amdgim_destroy_devices(); 191 | 192 | #ifdef CONFIG_GIM_HEARTBEAT_TIMER 193 | delete_heartbeat_timer(); 194 | #endif 195 | release_all_adapters(); 196 | 197 | driver_remove_file(&gim_driver.driver, &driver_attr_sriov); 198 | pci_unregister_driver(&gim_driver); 199 | 200 | 201 | gim_exit_debug_interface(); 202 | } 203 | 204 | module_init(gim_init) 205 | module_exit(gim_exit) 206 | 207 | MODULE_VERSION(STR(DRV_VERSION)); 208 | 209 | MODULE_AUTHOR("Advanced Micro Devices, Inc."); 210 | MODULE_DESCRIPTION("GPU IOV MODULE"); 211 | MODULE_LICENSE("GPL and additional rights"); 212 | -------------------------------------------------------------------------------- /utils/gru/info.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017~2018 Advanced Micro Devices, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 | * OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | #include "info.h" 25 | #include "gru.h" 26 | 27 | static char *gru_help_message[] = { 28 | "Commands:", 29 | " help - show this help file", 30 | " list - list all GPUs", 31 | " status - show all GPU status", 32 | " bios - show all GPU bios", 33 | " open - open a GPU", 34 | " quit - release resources and quit\n", 35 | " 'help ' shows details of each command", 36 | "EOF", 37 | }; 38 | 39 | static char *gpu_help_message[] = { 40 | "Commands:", 41 | " help - show this help file", 42 | " list - list VFs under the GPU", 43 | " get - get a VF with specific setting", 44 | " release - release VF", 45 | " status - show all VF status", 46 | " reset - perform hotlink reset to GPU", 47 | " open - open a VF", 48 | " exit - return to upper layer command\n", 49 | " 'help ' shows details of each command", 50 | "EOF", 51 | }; 52 | 53 | static char *vf_help_message[] = { 54 | "Commands:", 55 | " help - show this help file", 56 | " status - show VF status", 57 | " clear - clear VF FB", 58 | " reset - perform function level reset to VF", 59 | " exit - return to upper layer command\n", 60 | " 'help ' shows details of each command", 61 | "EOF", 62 | }; 63 | 64 | static char *gru_open_message[] = { 65 | "open a GPU", 66 | " open ", 67 | " BusId - the GPU bus id", 68 | " use 'gpu info' to see all the GPUs", 69 | "EOF", 70 | }; 71 | 72 | static char *gru_list_message[] = { 73 | "List all GPUs", 74 | " list", 75 | "EOF", 76 | }; 77 | 78 | static char *gru_status_message[] = { 79 | "Show all GPU status", 80 | " status", 81 | "EOF", 82 | }; 83 | 84 | static char *gru_bios_message[] = { 85 | "Show all GPU bios", 86 | " bios", 87 | "EOF", 88 | }; 89 | 90 | static char *gpu_open_message[] = { 91 | "open a VF", 92 | " open ", 93 | " BusId - the VF bus id", 94 | " use 'list' to list all the VFs under the GPU", 95 | "EOF", 96 | }; 97 | 98 | static char *gpu_list_message[] = { 99 | "List all VFs under the GPU:", 100 | " list", 101 | "EOF", 102 | }; 103 | 104 | static char *gpu_get_message[] = { 105 | "Get a VF with specific setting:", 106 | " get ", 107 | " fb_start - the offset from the beginning of FB.", 108 | " the unit is MB, and the minimum offset alignment is 16MB.", 109 | " fb_size - the fb size for this VF.", 110 | " the unit is MB, the minimum size is 256MB, and the minimum size alignment is 16MB.", 111 | " gfx_partition - the GFX engine partitioning for this VF.", 112 | " the valid value is 1, 2, 4, 8, 16. ", 113 | " it specify the VF time slice to be the GPU GFX engine’s time or 1/2, 1/4, 1/8, 1/16 of a time slice.", 114 | "EOF", 115 | }; 116 | 117 | static char *gpu_status_message[] = { 118 | "Show all VF status:", 119 | " status", 120 | "EOF", 121 | }; 122 | 123 | static char *vf_status_message[] = { 124 | "Show the VF status", 125 | " status", 126 | "EOF", 127 | }; 128 | 129 | static char *vf_clear_message[] = { 130 | "Clear the VF FB with the pattern", 131 | " clear ", 132 | " pattern - value to write to FB", 133 | "EOF", 134 | }; 135 | 136 | static char *gpu_release_message[] = { 137 | "Release a VF. The VF which was returned from 'get'", 138 | " release ", 139 | " BusId - VF bus ID", 140 | "EOF", 141 | }; 142 | 143 | static char *gpu_reset_message[] = { 144 | "Perform hotlink reset to GPU", 145 | " reset", 146 | "EOF", 147 | }; 148 | 149 | static char *vf_reset_message[] = { 150 | "Perform function level reset to VF", 151 | " reset", 152 | "EOF", 153 | }; 154 | 155 | message_entry_t gru_message_box[] = { 156 | {"help", gru_help_message}, 157 | {"list", gru_list_message}, 158 | {"status", gru_status_message}, 159 | {"bios", gru_bios_message}, 160 | {"open", gru_open_message}, 161 | {NULL, NULL}, 162 | }; 163 | 164 | message_entry_t gpu_message_box[] = { 165 | {"help", gpu_help_message}, 166 | {"list", gpu_list_message}, 167 | {"get", gpu_get_message}, 168 | {"release", gpu_release_message}, 169 | {"status", gpu_status_message}, 170 | {"reset", gpu_reset_message}, 171 | {"open", gpu_open_message}, 172 | {NULL, NULL}, 173 | }; 174 | 175 | message_entry_t vf_message_box[] = { 176 | {"help", vf_help_message}, 177 | {"status", vf_status_message}, 178 | {"clear", vf_clear_message}, 179 | {"reset", vf_reset_message}, 180 | {NULL, NULL}, 181 | }; 182 | 183 | void print_info(char **info) 184 | { 185 | if (info == NULL) 186 | return; 187 | 188 | while (strcmp(*info, "EOF")) { 189 | GRU_LOG("%s", *info); 190 | info++; 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /drv/gim_pci.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__PCI_H 24 | #define _GPU_IOV_MODULE__PCI_H 25 | 26 | #include "gim_kcl_type.h" 27 | 28 | /* PCI_EXT_CAP_ID_GPUIOV is equal to PCI_EXT_CAP_ID_VNDR.*/ 29 | #define PCI_GPUIOV_MAX_VFS 16 30 | struct pci_gpu_iov { 31 | int pos; 32 | 33 | kcl_type_u8 version; 34 | 35 | /* VSEC definition. */ 36 | kcl_type_u16 vsec_id; 37 | kcl_type_u8 vsec_rev; 38 | kcl_type_u16 vsec_len; 39 | 40 | kcl_type_u8 func_id; 41 | kcl_type_u8 next_func_id; 42 | 43 | kcl_type_u8 context_size; 44 | /* 0: local frame buffer, 1: system memory. */ 45 | kcl_type_u8 context_loc; 46 | kcl_type_u32 context_offset; 47 | 48 | kcl_type_u16 total_fb_available; 49 | kcl_type_u16 total_fb_consumed; 50 | 51 | kcl_type_u16 vf_fb_size[PCI_GPUIOV_MAX_VFS]; 52 | kcl_type_u16 vf_fb_offset[PCI_GPUIOV_MAX_VFS]; 53 | }; 54 | 55 | 56 | 57 | /* GPU Virtualization */ 58 | #define PCI_EXT_CAP_ID__GPUIOV 0x0b 59 | 60 | #define PCI_GPUIOV_CAP 0x02 /* 16bits */ 61 | #define PCI_GPUIOV_CAP__VER(x) ((x)&0xf) 62 | #define PCI_GPUIOV_NEXT_CAP__OFFSET(x) ((x)>>4) 63 | 64 | #define PCI_GPUIOV_VSEC 0x04 /* 32bits*/ 65 | #define PCI_GPUIOV_VSEC__ID__GPU_IOV 0x02 66 | #define PCI_GPUIOV_VSEC__ID(x) ((x) & 0xffff) 67 | #define PCI_GPUIOV_VSEC__REV(x) (((x) >> 16) & 0x0f) 68 | #define PCI_GPUIOV_VSEC__LENGTH(x) ((x)>>20) 69 | 70 | 71 | #define PCI_GPUIOV_CMD_CONTROL 0x0c /* 8bits */ 72 | #define PCI_GPUIOV_FCN_ID 0x0d /* 8bits */ 73 | #define PCI_GPUIOV_NXT_FCN_ID 0x0e /* 8bits */ 74 | 75 | #define PCI_GPUIOV_CMD_STATUS 0x10 /* 8bits */ 76 | 77 | #define PCI_GPUIOV_RESET_CONTROL 0x14 /* 8bits */ 78 | 79 | 80 | #define PCI_GPUIOV_RESET_NOTIFICATION 0x18 /* 32bits */ 81 | #define PCI_GPUIOV_VM_INIT_STATUS 0x1c /* 32bits */ 82 | 83 | #define PCI_GPUIOV_CNTXT 0x20 /* 32bits */ 84 | #define PCI_GPUIOV_CNTXT__SIZE(x) ((x) & 0x7f) 85 | #define PCI_GPUIOV_CNTXT__LOC(x) (((x) >> 7) & 0x01) 86 | #define PCI_GPUIOV_CNTXT__OFFSET(x) ((x) >> 10) 87 | 88 | 89 | #define PCI_GPUIOV_CNTXT__LOC_IN_FB 0 90 | #define PCI_GPUIOV_CNTXT__LOC_IN_SYS 1 91 | 92 | #define PCI_GPUIOV_CNTXT__SIZE__PUT(x) ((x) & 0x7f) 93 | #define PCI_GPUIOV_CNTXT__LOC__PUT(x) (((x) & 0x01) << 7) 94 | #define PCI_GPUIOV_CNTXT__OFFSET__PUT(x) (((x) & 0x3fffff) << 10) 95 | 96 | #define PCI_GPUIOV_TOTAL_FB_AVAILABLE 0x24 /* 16bits */ 97 | #define PCI_GPUIOV_TOTAL_FB_CONSUMED 0x26 /* 16bits */ 98 | 99 | #define PCI_GPUIOV_AUTO_SCH_OFFSET 0x2a /* 8bits */ 100 | #define PCI_GPUIOV_DISP_OFFSET 0x2b /* 8bits */ 101 | 102 | 103 | #define PCI_GPUIOV_VF0_FB_SIZE 0x2c /* 16bits */ 104 | #define PCI_GPUIOV_VF0_FB_OFFSET 0x2e /* 16bits */ 105 | 106 | #define PCI_GPUIOV_VF1_FB_SIZE 0x30 /* 16bits */ 107 | #define PCI_GPUIOV_VF1_FB_OFFSET 0x32 /* 16bits */ 108 | 109 | #define PCI_GPUIOV_VF2_FB_SIZE 0x34 /* 16bits */ 110 | #define PCI_GPUIOV_VF2_FB_OFFSET 0x36 /* 16bits */ 111 | 112 | #define PCI_GPUIOV_VF3_FB_SIZE 0x38 /* 16bits */ 113 | #define PCI_GPUIOV_VF3_FB_OFFSET 0x3a /* 16bits */ 114 | 115 | #define PCI_GPUIOV_VF4_FB_SIZE 0x3c /* 16bits */ 116 | #define PCI_GPUIOV_VF4_FB_OFFSET 0x3e /* 16bits */ 117 | 118 | #define PCI_GPUIOV_VF5_FB_SIZE 0x40 /* 16bits */ 119 | #define PCI_GPUIOV_VF5_FB_OFFSET 0x42 /* 16bits */ 120 | 121 | #define PCI_GPUIOV_VF6_FB_SIZE 0x44 /* 16bits */ 122 | #define PCI_GPUIOV_VF6_FB_OFFSET 0x46 /* 16bits */ 123 | 124 | #define PCI_GPUIOV_VF7_FB_SIZE 0x48 /* 16bits */ 125 | #define PCI_GPUIOV_VF7_FB_OFFSET 0x4a /* 16bits */ 126 | 127 | #define PCI_GPUIOV_VF8_FB_SIZE 0x4c /* 16bits */ 128 | #define PCI_GPUIOV_VF8_FB_OFFSET 0x4e /* 16bits */ 129 | 130 | #define PCI_GPUIOV_VF9_FB_SIZE 0x50 /* 16bits */ 131 | #define PCI_GPUIOV_VF9_FB_OFFSET 0x52 /* 16bits */ 132 | 133 | #define PCI_GPUIOV_VF10_FB_SIZE 0x54 /* 16bits */ 134 | #define PCI_GPUIOV_VF10_FB_OFFSET 0x56 /* 16bits */ 135 | 136 | #define PCI_GPUIOV_VF11_FB_SIZE 0x58 /* 16bits */ 137 | #define PCI_GPUIOV_VF11_FB_OFFSET 0x5a /* 16bits */ 138 | 139 | #define PCI_GPUIOV_VF12_FB_SIZE 0x5c /* 16bits */ 140 | #define PCI_GPUIOV_VF12_FB_OFFSET 0x5e /* 16bits */ 141 | 142 | #define PCI_GPUIOV_VF13_FB_SIZE 0x60 /* 16bits */ 143 | #define PCI_GPUIOV_VF13_FB_OFFSET 0x62 /* 16bits */ 144 | 145 | #define PCI_GPUIOV_VF14_FB_SIZE 0x64 /* 16bits */ 146 | #define PCI_GPUIOV_VF14_FB_OFFSET 0x66 /* 16bits */ 147 | 148 | #define PCI_GPUIOV_VF15_FB_SIZE 0x68 /* 16bits */ 149 | #define PCI_GPUIOV_VF15_FB_OFFSET 0x6c /* 16bits */ 150 | 151 | #define PCI_SRIOV_CAP_ARI_PRESERVED 0x2 152 | 153 | struct pci_device_id; 154 | uint32_t get_bdf(struct pci_dev *pdev); 155 | int enumerate_vfs(struct pci_dev *dev, int count, struct pci_dev *vf_devices[]); 156 | int enumerate_all_pfs(const struct pci_device_id *device_list, int count, 157 | struct pci_dev *pf_devices[]); 158 | int get_func_id(struct pci_dev *pf_dev, struct pci_dev *vf_dev); 159 | 160 | int sriov_is_ari_enabled(struct pci_dev *pf_dev); 161 | int sriov_enable_ari(struct pci_dev *pf_dev); 162 | void enable_device(struct pci_dev *dev); 163 | 164 | #endif 165 | 166 | -------------------------------------------------------------------------------- /docs/gim_runtime_configuration: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | GIM Runtime Configuration 24 | 25 | The GIM configuration file /etc/gim_config can be created after loading gim.ko 26 | for the first time. It can be used to modify options for GIM. 27 | 28 | There are 7 options: vf_num, pf_fb, vf_fb, fb_option, sched_interval, 29 | sched_option, fb_clear. 30 | 31 | 1. vf_num 32 | The "vf_num" specifies the number of virtual functions to be enabled. It can 33 | be set to any number between 0 and 16. 34 | 35 | vf_num = 0 36 | It enables maximum available virtual functions that the specific in 37 | vendor defined CAP register SRIOV_NUM_VFS in pci config space. 38 | 39 | vf_num=[1…16] 40 | enables the specified number of VFs on the bus when GIM is loaded. If the 41 | value is set to larger than the GPU/VBios combination can support it will 42 | be reduced to the number defined in register SRIOV_NUM_VFS. 43 | 44 | 2. pf_fb 45 | The “pf_fb” parameter specifies the amount of Frame Buffer memory reserved 46 | for the PF. The Frame Buffer size is in units of 1 MB but should be specified 47 | in multiples of 16MB. If the size is not specified in a multiple of 16MB, the 48 | size will be rounded down to the nearest 16MB boundary. Valid values are 49 | between 0 and 65536. A value of 65536 represents 64G which is far beyond the 50 | 8GB FB size of the S7150. Setting bigger PF frame buffer leads to less VF 51 | frame buffer left. 52 | 53 | Min_PF_FB_Size is same as BAR0 size. But if "large bar0" feature is 54 | enabled, Min_PF_FB_Size will be fixed to 16M. 55 | 56 | Max_PF_FB_Size = total FB - (Min_VF_FB_Size * vf_num) - CSA - Alignment. 57 | total FB is get from register TOTAL_FB_AVAILABLE in PCI header. 58 | Min_VF_FB_Size is VF FB BAR0 aperture size. CSA means context save/restore 59 | area. 60 | 61 | If a value is specified above the Max_PF_FB_Size, then the real PF FB size 62 | will be Max_PF_FB_Size. 63 | 64 | If a value is specified below the Min_PF_FB_Size, then the real PF FB size 65 | will be Min_PF_FB_Size. 66 | 67 | pf_fb=[0…Min_PF_FB_Size] 68 | PF FB size is Min_PF_FB_Size. 69 | 70 | pf_fb=[Min_PF_FB_Size…Max_PF_FB_Size] 71 | Size of PF FB reservation in MB units. The PF FB should be in multiple of 16M 72 | unit. If set to a value which is not in multiple of 16M, the size will be 73 | rounded down to nearest 16M boundary. 74 | 75 | pf_fb=[16…8176] 76 | PF FB size is Max_PF_FB_Size. 77 | 78 | 3. vf_fb 79 | The “vf_fb” specifies the amount of VF FB size in the unit of MB. The valid 80 | values are between 0 and 65536. vf_fb should be set to a multiple of 16M, any 81 | value which is not in a multiple of 16M will be rounded down to the nearest 82 | 16M boundary. A value of 65536 means 64G which is far beyond the actual FB 83 | size 8G on S7150.i VF FB is assigned after PF FB. 84 | 85 | Min_VF_FB_Size = VF FB BAR0 aperture size. 86 | 87 | Max_VF_FB_Size = (total FB - PF FB - reservation)/vf_num, and round down to 88 | multiple of 16M. 89 | 90 | vf_fb = 0 91 | Divide the available FrameBuffer equally amongst the VFs. Each VF FB size is 92 | Max_VF_FB_Size. 93 | 94 | vf_fb[1..65536] 95 | Currently, the S7150 has set each VF to have 256M FB aperture in the SRIOV 96 | BAR. The VF FB size cannot be smaller than the VF aperture and will be 97 | adjusted accordingly. Under some circumstances where SBIOS has difficulties 98 | allocating resources for SRIOV a special VBIOS is required that will specify 99 | a smaller BAR size as 128MB for each VF. 100 | 101 | if vf_fb < Min_VF_FB_Size, the final real frame buffer is Min_VF_FB_Size. 102 | if vf_fb > Max_VF_FB_Size, the final real frame buffer is Max_VF_FB_Size. 103 | otherwise, the final real frame buffer is same as vf_fb. 104 | 105 | This option is valid only when fb_option=0. 106 | 107 | 4. fb_option 108 | The "fb_option" specifies the VF frame buffer partitioning method. It only 109 | supports two values: 110 | 111 | fb_option = 0 112 | Divide the Frame Buffer equally amongst all of the available VFs. This is 113 | the default value. The size of the VF FB size can be modified by the vf_fb 114 | option. 115 | 116 | fb_option = 1 117 | Each VF can have a different FB size. It is not supported yet. 118 | 119 | 5. sched_interval 120 | Scheduling time quanta in milliseconds. Thed valid value are between 0 and 121 | 2000. 122 | 123 | sched_interval = 0 124 | default quanta(6ms) 125 | 126 | sched_interval = [1:2000] 127 | Real number of quanta in miliseconds. 128 | 129 | 6. sched_option 130 | The "sched_option" specifies the algorithm that will be used to determine how 131 | the GPU time is divided between the active VFs. It only supports two values: 132 | 133 | sched_option = 0 134 | Active VFs will get a time slice in a "round robin" style. The size of the time 135 | slice is determined by the "sched_interval" option. 136 | 137 | sched_option = 1 138 | All VFs will share HW resoruce equally by almost same time slice in turns. Even 139 | the VF is stop, the VF still can occupy its HW resource. 140 | 141 | 7. fb_clear 142 | Clear the VRAM for VF 143 | 144 | fb_clear = 0 145 | Default value.Skip to clear framebuffer 146 | 147 | fb_clear = 1 148 | Clear FB of VF when VF is free or down 149 | -------------------------------------------------------------------------------- /utils/gru/command.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017~2018 Advanced Micro Devices, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 | * OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | #include "gru.h" 25 | #include "info.h" 26 | #include "hw_context.h" 27 | 28 | int cmd_gru_help(char *param) 29 | { 30 | message_entry_t *entry; 31 | 32 | for (entry = gru_message_box; entry->command; entry++){ 33 | if ((param == NULL) || (0 == strcmp(entry->command, param))) { 34 | print_info(entry->message); 35 | return RET_OK; 36 | } 37 | } 38 | GRU_LOG("Invalid command!"); 39 | return RET_ERROR; 40 | } 41 | 42 | int cmd_gru_list(char *param) 43 | { 44 | show_gpuinfo(); 45 | return RET_OK; 46 | } 47 | 48 | int cmd_gru_status(char *param) 49 | { 50 | show_gpuvs(); 51 | return RET_OK; 52 | } 53 | 54 | int cmd_gru_bios(char *param) 55 | { 56 | show_gpubios(); 57 | return RET_OK; 58 | } 59 | 60 | int cmd_gru_open(char *param) 61 | { 62 | if (param == NULL) { 63 | GRU_LOG("Invalid parameters!"); 64 | return RET_ERROR; 65 | } 66 | 67 | char bus_id[13]; 68 | 69 | sscanf(param, "%s", &bus_id); 70 | 71 | if (strlen(bus_id) != 12) { 72 | GRU_LOG("Invalid GPU bus ID %s", bus_id); 73 | return RET_ERROR; 74 | } 75 | 76 | return open_gpu(bus_id); 77 | } 78 | 79 | int cmd_gru_quit(char *param) 80 | { 81 | return RET_EXIT; 82 | } 83 | 84 | int cmd_gpu_help(char *param) 85 | { 86 | message_entry_t *entry; 87 | 88 | for (entry = gpu_message_box; entry->command; entry++){ 89 | if ((param == NULL) || (0 == strcmp(entry->command, param))) { 90 | print_info(entry->message); 91 | return RET_OK; 92 | } 93 | } 94 | GRU_LOG("Invalid command!"); 95 | return RET_ERROR; 96 | } 97 | 98 | int cmd_gpu_list(char *param) 99 | { 100 | list_vf(); 101 | 102 | return RET_OK; 103 | } 104 | 105 | int cmd_gpu_get(char *param) 106 | { 107 | if (param == NULL) { 108 | GRU_LOG("Invalid parameters!"); 109 | return RET_ERROR; 110 | } 111 | 112 | char fb_start[15]; 113 | char fb_size[15]; 114 | char gfx_partition[15]; 115 | 116 | sscanf(param, "%s %s %s", &fb_start, &fb_size, &gfx_partition); 117 | get_vf(fb_start, fb_size, gfx_partition); 118 | 119 | return RET_OK; 120 | } 121 | 122 | int cmd_gpu_release(char *param) 123 | { 124 | if (param == NULL) { 125 | GRU_LOG("Invalid parameters!"); 126 | return RET_ERROR; 127 | } 128 | 129 | char bus_id[13]; 130 | 131 | sscanf(param, "%s", &bus_id); 132 | 133 | if (strlen(bus_id) != 12) { 134 | GRU_LOG("Invalid VF bus ID %s", bus_id); 135 | return RET_ERROR; 136 | } 137 | 138 | release_vf(bus_id); 139 | 140 | return RET_OK; 141 | } 142 | 143 | 144 | int cmd_gpu_status(char *param) 145 | { 146 | gpu_status(); 147 | 148 | return RET_OK; 149 | } 150 | 151 | int cmd_gpu_reset(char *param) 152 | { 153 | char cmd[100]; 154 | 155 | sprintf(cmd,"echo 1 >/sys/bus/pci/devices/%s/hotlink_reset", get_current_gpu()); 156 | system(cmd); 157 | sprintf(cmd,"cat /sys/bus/pci/devices/%s/hotlink_reset", get_current_gpu()); 158 | system(cmd); 159 | 160 | return RET_OK; 161 | } 162 | 163 | int cmd_vf_help(char *param) 164 | { 165 | message_entry_t *entry; 166 | 167 | for (entry = vf_message_box; entry->command; entry++){ 168 | if ((param == NULL) || (0 == strcmp(entry->command, param))) { 169 | print_info(entry->message); 170 | return RET_OK; 171 | } 172 | } 173 | GRU_LOG("Invalid command!"); 174 | return RET_ERROR; 175 | } 176 | 177 | int cmd_vf_reset(char *param) 178 | { 179 | char cmd[100]; 180 | 181 | sprintf(cmd,"echo 1 >/sys/bus/pci/devices/%s/flr", get_current_vf()); 182 | system(cmd); 183 | sprintf(cmd,"cat /sys/bus/pci/devices/%s/flr", get_current_vf()); 184 | system(cmd); 185 | 186 | return RET_OK; 187 | } 188 | 189 | int cmd_vf_status(char *param) 190 | { 191 | char cmd[50]; 192 | sprintf(cmd,"cat /sys/bus/pci/devices/%s/gpuvf", get_current_vf()); 193 | system(cmd); 194 | 195 | return RET_OK; 196 | } 197 | 198 | int cmd_vf_clear(char *param) 199 | { 200 | if (param == NULL) { 201 | GRU_LOG("Invalid parameters!"); 202 | return RET_ERROR; 203 | } 204 | 205 | char pattern[10]; 206 | 207 | sscanf(param, "%s", &pattern); 208 | char cmd[100]; 209 | sprintf(cmd,"echo %s > /sys/bus/pci/devices/%s/clrvffb", pattern, get_current_vf()); 210 | system(cmd); 211 | sprintf(cmd,"cat /sys/bus/pci/devices/%s/clrvffb", get_current_vf()); 212 | system(cmd); 213 | 214 | return RET_OK; 215 | } 216 | 217 | int cmd_gpu_exit(char *param) 218 | { 219 | return close_gpu(); 220 | } 221 | 222 | int cmd_vf_exit(char *param) 223 | { 224 | return close_vf(); 225 | } 226 | 227 | int cmd_gpu_open(char *param) 228 | { 229 | if (param == NULL) { 230 | GRU_LOG("Invalid parameters!"); 231 | return RET_ERROR; 232 | } 233 | 234 | char bus_id[13]; 235 | 236 | sscanf(param, "%s", &bus_id); 237 | 238 | if (strlen(bus_id) != 12) { 239 | GRU_LOG("Invalid VF bus ID %s", bus_id); 240 | return RET_ERROR; 241 | } 242 | 243 | return open_vf(bus_id); 244 | } 245 | -------------------------------------------------------------------------------- /drv/gim_pci.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "gim_pci.h" 28 | #include "gim_debug.h" 29 | 30 | uint32_t get_bdf(struct pci_dev *pdev) 31 | { 32 | return ((pdev->bus->number << 8) | pdev->devfn); 33 | } 34 | 35 | static unsigned short get_vf_deviceid(struct pci_dev *dev) 36 | { 37 | int pos; 38 | unsigned short device = 0; 39 | 40 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); 41 | pci_read_config_word(dev, pos + PCI_SRIOV_VF_DID, &device); 42 | 43 | return device; 44 | } 45 | 46 | static unsigned short get_vf_offset(struct pci_dev *dev) 47 | { 48 | int pos; 49 | unsigned short vf_offset = 0; 50 | 51 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); 52 | pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &vf_offset); 53 | return vf_offset; 54 | } 55 | 56 | static unsigned short get_vf_stride(struct pci_dev *dev) 57 | { 58 | int pos; 59 | unsigned short vf_stride = 0; 60 | 61 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); 62 | pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &vf_stride); 63 | return vf_stride; 64 | } 65 | 66 | static unsigned short get_num_vfs(struct pci_dev *dev) 67 | { 68 | int pos; 69 | unsigned short num_vfs = 0; 70 | 71 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); 72 | pci_read_config_word(dev, pos + PCI_SRIOV_NUM_VF, &num_vfs); 73 | return num_vfs; 74 | } 75 | 76 | static int is_attached_vf(struct pci_dev *pf_dev, struct pci_dev *vf_dev) 77 | { 78 | unsigned short vf_stride = get_vf_stride(pf_dev); 79 | unsigned short num_vfs = get_num_vfs(pf_dev); 80 | uint32_t vf_start = get_bdf(pf_dev) + get_vf_offset(pf_dev); 81 | uint32_t vf_bdf = get_bdf(vf_dev); 82 | int is_found = 0; 83 | unsigned short i; 84 | 85 | for (i = 0; i < num_vfs; ++i) { 86 | if (vf_bdf == vf_start) 87 | is_found = 1; 88 | 89 | vf_start += vf_stride; 90 | } 91 | return is_found; 92 | } 93 | 94 | int get_func_id(struct pci_dev *pf_dev, struct pci_dev *vf_dev) 95 | { 96 | int func_id = -1; 97 | unsigned short vf_stride = get_vf_stride(pf_dev); 98 | unsigned short num_vfs = get_num_vfs(pf_dev); 99 | uint32_t vf_start = get_bdf(pf_dev) + get_vf_offset(pf_dev); 100 | uint32_t vf_bdf = get_bdf(vf_dev); 101 | unsigned short i; 102 | 103 | for (i = 0; i < num_vfs; ++i) { 104 | if (vf_bdf == vf_start) 105 | func_id = i; 106 | 107 | vf_start += vf_stride; 108 | } 109 | return func_id; 110 | } 111 | 112 | int enumerate_vfs(struct pci_dev *dev, int count, struct pci_dev *vf_devices[]) 113 | { 114 | struct pci_dev *vfdev = NULL; 115 | int vf_count = 0; 116 | unsigned short device_id = get_vf_deviceid(dev); 117 | 118 | while ((vfdev = pci_get_device(dev->vendor, device_id, vfdev)) && 119 | vf_count < count) { 120 | if (is_attached_vf(dev, vfdev)) { 121 | vf_devices[vf_count++] = vfdev; 122 | gim_info("vf found: %02x:%x.%x\n", vfdev->bus->number, 123 | (vfdev->devfn>>3), (vfdev->devfn & 0x7)); 124 | } 125 | } 126 | return vf_count; 127 | } 128 | 129 | int enumerate_all_pfs(const struct pci_device_id *device_list, int count, 130 | struct pci_dev *pf_devices[]) 131 | { 132 | struct pci_dev *pfdev = NULL; 133 | int pf_count = 0; 134 | int list_count = 0; 135 | 136 | while (device_list[list_count].vendor != 0 && 137 | device_list[list_count].device != 0) { 138 | while ((pfdev = pci_get_device(device_list[list_count].vendor, 139 | device_list[list_count].device, 140 | pfdev))) { 141 | if (pf_count < count) { 142 | pf_devices[pf_count++] = pfdev; 143 | } else { 144 | gim_info("More than %d phyiscal devicesfound\n!", 145 | count); 146 | } 147 | } 148 | /* Search for next device id */ 149 | list_count++; 150 | pfdev = NULL; 151 | } 152 | return pf_count; 153 | } 154 | 155 | int sriov_is_ari_enabled(struct pci_dev *dev) 156 | { 157 | uint16_t capabilities; 158 | uint16_t control; 159 | int pos; 160 | 161 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); 162 | pci_read_config_word(dev, pos + PCI_SRIOV_CAP, &capabilities); 163 | 164 | gim_info("PCI_SRIOV_CAP = 0x%08x\n", capabilities); 165 | 166 | if (!(capabilities & PCI_SRIOV_CAP_ARI_PRESERVED)) { 167 | gim_info("PCI_SRIOV_CAP_ARI_PRESERVED is not set.\n"); 168 | gim_info("--> Assume ARI is not enabled\n"); 169 | return 0; 170 | } 171 | 172 | pci_read_config_word(dev, pos + PCI_SRIOV_CTRL, &control); 173 | 174 | gim_info("PCI_SRIOV_CTRL = 0x%08x\n", control); 175 | 176 | if (control & PCI_SRIOV_CTRL_ARI) { 177 | gim_info("PCI_SRIOV_CTRL_ARI is set --> ARI is supported\n"); 178 | return 1; 179 | } 180 | 181 | gim_info("PCI_SRIOV_CTRL_ARI is not set --> ARI is not supported\n"); 182 | 183 | return 0; 184 | } 185 | 186 | int sriov_enable_ari(struct pci_dev *pf_dev) 187 | { 188 | /* We don't currently support enabling the ARI if it is not already 189 | * enable 190 | * Enabling ARI involves determining the path from the root port, 191 | * through any switches and finally to the end-point. 192 | * 193 | * Along the path we need to check if ARI capability is supported and 194 | * if it is we need to turn on the ARI control bit. 195 | * If anything in the path fails then ARI cannot be enabled. 196 | */ 197 | return 0; 198 | } 199 | 200 | void enable_device(struct pci_dev *dev) 201 | { 202 | unsigned short cmd = 0; 203 | 204 | pci_read_config_word(dev, PCI_COMMAND, &cmd); 205 | cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); 206 | pci_write_config_word(dev, PCI_COMMAND, cmd); 207 | } 208 | -------------------------------------------------------------------------------- /drv/gim_gpuiov.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | #include "gim_pci.h" 27 | #include "gim_adapter.h" 28 | #include "gim_gpuiov.h" 29 | 30 | #include "gim_debug.h" 31 | #include "gim_interface.h" 32 | 33 | int pci_gpu_iov_init(struct pci_dev *dev, struct pci_gpu_iov *gpuiov) 34 | { 35 | int off; 36 | int pos; 37 | int is_found = 0; 38 | kcl_type_u32 data; 39 | 40 | gpuiov->pos = 0; 41 | 42 | if (!pci_is_pcie(dev)) 43 | return -ENODEV; 44 | 45 | /* Look for the GPU-IOV capability structure. */ 46 | /* It will be under the Vendor specific code */ 47 | pos = 0; 48 | while ((pos = pci_find_next_ext_capability(dev, 49 | pos, 50 | PCI_EXT_CAP_ID_VNDR))) { 51 | kcl_type_u32 vsec = 0; 52 | 53 | off = pos + PCI_GPUIOV_VSEC; 54 | pci_read_config_dword(dev, off, &vsec); 55 | gpuiov->vsec_id = PCI_GPUIOV_VSEC__ID(vsec); 56 | 57 | if (gpuiov->vsec_id == PCI_GPUIOV_VSEC__ID__GPU_IOV) { 58 | gpuiov->vsec_rev = PCI_GPUIOV_VSEC__REV(vsec); 59 | gpuiov->vsec_len = PCI_GPUIOV_VSEC__LENGTH(vsec); 60 | is_found = 1; 61 | break; 62 | } 63 | } 64 | 65 | if (!is_found) { 66 | gim_err("AMD GIM pci_gpu_iov_init: no GPU_IOV caps found.\n"); 67 | return -ENODEV; 68 | } 69 | 70 | gpuiov->pos = pos; 71 | 72 | off = gpuiov->pos + PCI_GPUIOV_FCN_ID; 73 | pci_read_config_byte(dev, off, &gpuiov->func_id); 74 | 75 | off = gpuiov->pos + PCI_GPUIOV_NXT_FCN_ID; 76 | pci_read_config_byte(dev, off, &gpuiov->next_func_id); 77 | 78 | off = gpuiov->pos + PCI_GPUIOV_CNTXT; 79 | pci_read_config_dword(dev, off, &data); 80 | gpuiov->context_size = PCI_GPUIOV_CNTXT__SIZE(data); 81 | gpuiov->context_loc = PCI_GPUIOV_CNTXT__LOC(data); 82 | gpuiov->context_offset = PCI_GPUIOV_CNTXT__OFFSET(data); 83 | 84 | off = gpuiov->pos + PCI_GPUIOV_TOTAL_FB_AVAILABLE; 85 | pci_read_config_word(dev, off, &gpuiov->total_fb_available); 86 | 87 | gim_info("total_fb_available = %d\n ", gpuiov->total_fb_available); 88 | gim_info("AMD GIM pci_gpu_iov_init pos = %x\n", gpuiov->pos); 89 | gim_info("AMD GIM pci_gpu_iov_init total_fb_available = %x\n", 90 | gpuiov->total_fb_available); 91 | 92 | return 0; 93 | } 94 | 95 | int set_gpuiov_context(struct pci_dev *dev, 96 | struct pci_gpu_iov *gpuiov, 97 | kcl_type_u8 context_size, kcl_type_u8 context_loc, 98 | kcl_type_u32 context_offset) 99 | { 100 | int off; 101 | kcl_type_u32 data; 102 | 103 | if (gpuiov->pos == 0) 104 | return -1; 105 | 106 | data = TO_256KBYTES(MBYTES_TO_BYTES(context_offset))/context_size; 107 | data = PCI_GPUIOV_CNTXT__SIZE__PUT(context_size) 108 | | PCI_GPUIOV_CNTXT__LOC__PUT(context_loc) 109 | | PCI_GPUIOV_CNTXT__OFFSET__PUT(data); 110 | off = gpuiov->pos + PCI_GPUIOV_CNTXT; 111 | pci_write_config_dword(dev, off, data); 112 | 113 | gpuiov->context_size = context_size; 114 | gpuiov->context_loc = context_loc; 115 | gpuiov->context_offset = context_offset; 116 | 117 | return 0; 118 | } 119 | 120 | int set_gpuiov_function_id(struct pci_dev *dev, 121 | struct pci_gpu_iov *gpuiov, 122 | kcl_type_u8 function_id) 123 | { 124 | int off; 125 | 126 | if (gpuiov->pos == 0) 127 | return -1; 128 | 129 | off = gpuiov->pos + PCI_GPUIOV_FCN_ID; 130 | pci_write_config_byte(dev, off, function_id); 131 | 132 | gpuiov->func_id = function_id; 133 | 134 | return 0; 135 | } 136 | 137 | int set_gpuiov_next_function_id(struct pci_dev *dev, 138 | struct pci_gpu_iov *gpuiov, 139 | kcl_type_u8 next_func_id) 140 | { 141 | int off; 142 | 143 | if (gpuiov->pos == 0) 144 | return -1; 145 | 146 | off = gpuiov->pos + PCI_GPUIOV_NXT_FCN_ID; 147 | pci_write_config_byte(dev, off, next_func_id); 148 | 149 | gpuiov->next_func_id = next_func_id; 150 | 151 | return 0; 152 | } 153 | 154 | int set_gpuiov_total_fb_consumed(struct pci_dev *dev, 155 | struct pci_gpu_iov *gpuiov, 156 | kcl_type_u16 total_fb_consumed) 157 | { 158 | int off; 159 | 160 | if (gpuiov->pos == 0) 161 | return -1; 162 | 163 | off = gpuiov->pos + PCI_GPUIOV_TOTAL_FB_CONSUMED; 164 | pci_write_config_word(dev, off, total_fb_consumed); 165 | gpuiov->total_fb_consumed = total_fb_consumed; 166 | 167 | return 0; 168 | } 169 | 170 | int set_gpuiov_vf_frame_buffer(struct pci_dev *dev, 171 | struct pci_gpu_iov *gpuiov, 172 | int vf, kcl_type_u16 size, kcl_type_u16 offset) 173 | { 174 | int off; 175 | kcl_type_u32 data; 176 | 177 | data = (((size)>>4) - 1) | ((offset >> 4) << 16); 178 | off = gpuiov->pos + PCI_GPUIOV_VF0_FB_SIZE + vf * sizeof(kcl_type_u32); 179 | pci_write_config_dword(dev, off, data); 180 | 181 | gpuiov->vf_fb_size[vf] = size; 182 | gpuiov->vf_fb_offset[vf] = offset; 183 | 184 | return 0; 185 | } 186 | 187 | int set_gpuiov_command(struct pci_dev *dev, struct pci_gpu_iov *gpuiov, 188 | int command, int func_id, int next_func_id) 189 | { 190 | int off; 191 | kcl_type_u32 data; 192 | 193 | data = command | CMD_EXECUTE | (func_id << 8) | (next_func_id << 16); 194 | off = gpuiov->pos + PCI_GPUIOV_CMD_CONTROL; 195 | pci_write_config_dword(dev, off, data); 196 | 197 | return 0; 198 | } 199 | 200 | int get_vf_hw_fb_settings(struct pci_dev *pf_dev, 201 | struct pci_gpu_iov *gpuiov, 202 | int vf_id, uint32_t *fb_start, 203 | uint32_t *fb_size) 204 | { 205 | uint16_t size; 206 | uint16_t start; 207 | int off; 208 | 209 | off = gpuiov->pos + PCI_GPUIOV_VF0_FB_SIZE + (vf_id * 4); 210 | pci_read_config_word(pf_dev, off, &size); 211 | 212 | off = gpuiov->pos + PCI_GPUIOV_VF0_FB_OFFSET + (vf_id * 4); 213 | pci_read_config_word(pf_dev, off, &start); 214 | 215 | *fb_start = start * 16; /* Register is in units of 16MB */ 216 | *fb_size = size * 16; /* Register is in units of 16MB */ 217 | *fb_size += 16; /* Register is size - 16MB */ 218 | 219 | return 0; 220 | } 221 | -------------------------------------------------------------------------------- /utils/gru/console.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017~2018 Advanced Micro Devices, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 | * OTHER DEALINGS IN THE SOFTWARE. 21 | * 22 | */ 23 | 24 | #include "gru.h" 25 | #include "command.h" 26 | #include "hw_context.h" 27 | 28 | cmd_entry_t gru_command_table[] = { 29 | {"help", cmd_gru_help}, 30 | {"list", cmd_gru_list}, 31 | {"status", cmd_gru_status}, 32 | {"bios", cmd_gru_bios}, 33 | {"open", cmd_gru_open}, 34 | {"quit", cmd_gru_quit}, 35 | {NULL, NULL} 36 | }; 37 | 38 | cmd_entry_t gpu_command_table[] = { 39 | {"help", cmd_gpu_help}, 40 | {"list", cmd_gpu_list}, 41 | {"get", cmd_gpu_get}, 42 | {"release", cmd_gpu_release}, 43 | {"status", cmd_gpu_status}, 44 | {"reset", cmd_gpu_reset}, 45 | {"open", cmd_gpu_open}, 46 | {"exit", cmd_gpu_exit}, 47 | {NULL, NULL} 48 | }; 49 | 50 | cmd_entry_t vf_command_table[] = { 51 | {"help", cmd_vf_help}, 52 | {"status", cmd_vf_status}, 53 | {"clear", cmd_vf_clear}, 54 | {"reset", cmd_vf_reset}, 55 | {"exit", cmd_vf_exit}, 56 | {NULL, NULL} 57 | }; 58 | 59 | static char * dupstr (char* s) { 60 | char *r; 61 | 62 | r = (char*) xmalloc ((strlen (s) + 1)); 63 | strcpy (r, s); 64 | return (r); 65 | } 66 | 67 | static char* command_generator(const char* text, int state) 68 | { 69 | static int list_index, len; 70 | cmd_entry_t *command_table; 71 | char *name; 72 | 73 | if (!state) { 74 | list_index = 0; 75 | len = strlen (text); 76 | } 77 | 78 | if (is_gpu_opened()) { 79 | if (is_vf_opened()) { 80 | command_table = vf_command_table; 81 | } else { 82 | command_table = gpu_command_table; 83 | } 84 | } else { 85 | command_table = gru_command_table; 86 | } 87 | 88 | while (name = command_table[list_index].command) { 89 | list_index++; 90 | 91 | if (strncmp (name, text, len) == 0) 92 | return (dupstr(name)); 93 | } 94 | 95 | /* If no names matched, then return NULL. */ 96 | return ((char *)NULL); 97 | 98 | } 99 | 100 | static char** command_completion(const char *text, int start, int end) 101 | { 102 | char **matches; 103 | 104 | matches = (char **)NULL; 105 | 106 | if (start == 0) 107 | matches = rl_completion_matches ((char*)text, &command_generator); 108 | 109 | return (matches); 110 | 111 | } 112 | 113 | static int *parse_command(char *cmd, cmd_entry_t *cmdtable) 114 | { 115 | cmd_entry_t *current; 116 | char *action, *tail, *parms, *comment; 117 | 118 | if ((cmd == NULL)) { 119 | return RET_ERROR; 120 | } 121 | 122 | action = tail = parms = comment = NULL; 123 | 124 | if ((comment = strchr (cmd, '#')) != NULL) { 125 | comment[0] = '\n'; 126 | comment[1] = '\0'; 127 | } 128 | 129 | if ((action = strtok (cmd, " \t\r\n")) == NULL) { 130 | return RET_ERROR; 131 | } 132 | 133 | if ((tail = strtok (NULL, "\r\n")) != NULL) { 134 | parms = tail + strspn (tail, " \t"); 135 | } 136 | 137 | for (current = cmdtable; current->command; current++) { 138 | if (strcasecmp (action, current->command) == 0) { 139 | return (current->pAction (parms)); 140 | } 141 | } 142 | 143 | return RET_ERROR; 144 | } 145 | 146 | static int process_input(void) 147 | { 148 | int ret; 149 | char *input; 150 | rl_attempted_completion_function = command_completion; 151 | char prompt[30]; 152 | char *token; 153 | 154 | do { 155 | if (is_gpu_opened()) { 156 | char cur_gpu[13]; 157 | char *gpu_bf; 158 | 159 | strcpy(cur_gpu, get_current_gpu()); 160 | token = strtok(cur_gpu, ":"); 161 | gpu_bf = strtok(NULL, "\n"); 162 | if (is_vf_opened()) { 163 | char cur_vf[13]; 164 | char *vf_bf; 165 | strcpy(cur_vf, get_current_vf()); 166 | token = strtok(cur_vf, ":"); 167 | vf_bf = strtok(NULL, "\n"); 168 | sprintf(prompt, "GRU>GPU:%s>VF:%s> ", gpu_bf, vf_bf); 169 | input = readline(prompt); 170 | rl_bind_key('\t',rl_complete); 171 | 172 | if (!input) { 173 | return RET_ERROR; 174 | } 175 | add_history(input); 176 | ret = parse_command(input, vf_command_table); 177 | if (ret == RET_ERROR) { 178 | GRU_LOG("Error: Invalid command"); 179 | } 180 | } else { 181 | sprintf(prompt, "GRU>GPU:%s> ", gpu_bf); 182 | input = readline(prompt); 183 | rl_bind_key('\t',rl_complete); 184 | 185 | if (!input) { 186 | return RET_ERROR; 187 | } 188 | add_history(input); 189 | ret = parse_command(input, gpu_command_table); 190 | if (ret == RET_ERROR) { 191 | GRU_LOG("Error: Invalid command"); 192 | } 193 | } 194 | } else { 195 | input = readline("GRU> "); 196 | rl_bind_key('\t',rl_complete); 197 | 198 | if (!input) { 199 | return RET_ERROR; 200 | } 201 | add_history(input); 202 | ret = parse_command(input, gru_command_table); 203 | if (ret == RET_ERROR) { 204 | GRU_LOG("Error: Invalid command"); 205 | } 206 | } 207 | } while (ret != RET_EXIT); 208 | 209 | return ret; 210 | } 211 | 212 | static void handle_signal(void) 213 | { 214 | exit(0); 215 | } 216 | 217 | int main() 218 | { 219 | int ret; 220 | using_history(); 221 | if (signal(SIGINT, handle_signal) == SIG_ERR) { 222 | GRU_LOG("Failed to register interrupts with kernel"); 223 | } 224 | 225 | printf("\nGRU\n"); 226 | printf("Copyright (C) 2017~2018 Advanced Micro Devices, Inc.\n\n"); 227 | printf("Type 'help' for help. Optional launch parameter is index of card to use.\n"); 228 | 229 | ret = detect_device(); 230 | if (ret != RET_OK) 231 | { 232 | GRU_LOG("Detect device failed\n"); 233 | return RET_ERROR; 234 | } 235 | 236 | while (ret != RET_EXIT) { 237 | ret = process_input(); 238 | } 239 | 240 | exit(0); 241 | } 242 | -------------------------------------------------------------------------------- /docs/environment_setup: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | Environment Setup 24 | 25 | Platform 26 | -------- 27 | 1. Necessary HW features 28 | 29 | 2. BIOS setting 30 | 31 | Host Software 32 | ------------- 33 | 1.Ubuntu 16.04 server 34 | 1.1 OS installation and configuration 35 | 1.1.1 Select virtualization when installing. 36 | 37 | 1.2 Hypervisor installation and configuration 38 | 1.2.1 update the software and kernel 39 | a. apt-get update 40 | b. apt-get upgrade 41 | c. apt-get dist-upgrade 42 | 1.2.2 download the kernel source code and install the build dependency 43 | a. apt-get source linux-image-$(uname -r) to download the the current running version kernel. 44 | b. apt-get build-dep linux-image-$(uname -r) 45 | c. cd the download kernel source dir 46 | d. cp /boot/config-$(uname -r) ./.config or make oldconfig to create .config file with your running kernel's configuration 47 | e. apt-get install libncurses5 libncurses5-dev 48 | f. apt-get install qt3-dev-tools libqt3-mt-dev 49 | g. menuconfig (by default) 50 | 1.2.3 patch the kernel for SRIOV support and build kernel 51 | a. Apply the following patches 52 | patch < ./patch/0001-Added-legacy-endpoint-type-to-sriov-for-ubuntu-4.4.0-75-generic.diff 53 | patch < ./patch/0002-add-pci-io-access-cap-for-ubuntu-4.4.0-75-generic.diff 54 | b. make-kpkg -j N --initrd --append-to-version=my-very-own-kernel kernel-image kernel-headers to buile kernel 55 | where N is how many jobs to run in parallel (usually the number of CPUs you have), and my-very-own-kernel is 56 | a custom string to identify the build 57 | 1.2.4 Install kernel 58 | a. dpkg -i *.deb to install kernel-image and header which are ready after build compelete. 59 | 1.2.5 Blacklist amdgpu driver on the host system 60 | a. add "blacklist amdgpu" in /etc/modprobe.d/blacklist.conf 61 | b. update-initramfs -u 62 | 1.2.6 Enable IOMMU 63 | a. edit /etc/default/grub 64 | change GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" to GRUB_CMDLINE_LINUX_DEFAULT="quiet splash intel_iommu=on" if Intel CPU 65 | change GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" to GRUB_CMDLINE_LINUX_DEFAULT="quiet splash amd_iommu=on" if AMD CPU 66 | b. update-grub 67 | 68 | 1.3 GIM installation 69 | 1.3.1 build and install gim 70 | a. copy the gim source code to host machine. 71 | b. run gim.sh 72 | c. modprobe gim 73 | 74 | 75 | 2.CentOS7.3 76 | 2.1 OS installation and configuration 77 | 2.2 Hypervisor installation and configuration 78 | 2.3 GIM installation 79 | 80 | Guest Software 81 | -------------- 82 | Here is the assumption that on host system, the GIM driver has 83 | been successfully loaded and guest systems are properly installed. 84 | Also make sure that one virtualized AMD GPU device is assigned to 85 | the target guest system, which is normally done by adding PCI 86 | Host Device to the guest as a passthrough device(Note that one 87 | virtualized VGA device can not be shared by two or more running 88 | guest systems at the same time). Besides, the network on guest 89 | system should work fine. 90 | 91 | 1.Windows(R)7 64bit 92 | 1.1 Check the guest system IP address 93 | 1.2 Install UltraVNC server on the guest system 94 | 1.3 Download amdgpu-pro driver from(TBD) 95 | ****** 96 | and install the driver properly 97 | 1.4 Reboot the guest system after finishing installation. If the 98 | driver installation is successful,the startup screen should 99 | freeze at some point before login interface shows up 100 | 1.5 Connect the guest through VNC remote desktop a few seconds after 101 | the screen freezes 102 | 103 | 2.Windows(R)10 TH2 64bit 104 | 2.1 Check the guest system IP address 105 | 2.2 Install UltraVNC server on the guest system 106 | 2.3 Download amdgpu-pro driver from(TBD) 107 | ****** 108 | and install the driver properly. 109 | 2.4 Reboot the guest system after finishing installation.If the 110 | driver installation is successful,the startup screen should 111 | freeze at some point before login interface shows up and then 112 | turns to black. 113 | 2.5 Connect the guest through VNC remote desktop a few seconds after 114 | the black screen shows up 115 | 116 | 3.Ubuntu16.04 desktop 64bit 117 | 3.1 Check the guest system IP address 118 | 3.2 Install X11VNC server and config it to run at system 119 | startup 120 | 3.3 Run command "lspci | grep AMD" to check the BDF number 121 | of the AMD GPU device 122 | 3.4 Download amdgpu-pro driver from(TBD) 123 | ***** 124 | and intall the driver properly 125 | 3.5 In directory /usr/share/X11/xorg.conf.d, edit file 126 | 10-amdgpu-pro.conf and add the following section in it 127 | Section "Device" 128 | Identifier "amdgpu" 129 | Driver "amdgpu" 130 | BusID "PCI:xx:xx:xx" 131 | EndSection 132 | where xx:xx:xx is the BDF number in step 3.3 133 | 3.6 Edit the grub configuration to enter console mode at system 134 | startup 135 | 3.7 Edit file /etc/modprobe.d/blacklist.conf, add "blacklist amdgpu" 136 | to the end of the file, and run command "sudo update-initramfs -u 137 | -k all" 138 | 3.8 Reboot the guest system 139 | 3.9 Login guest system, load amdgpu driver by "modprobe amdgpu" and 140 | start the lightdm service 141 | 3.10 Connect the guest system through VNC remote desktop 142 | 143 | 4.CentOS7.3 64bit 144 | 4.1 Check the guest system IP address 145 | 4.2 Install X11VNC server and config it to run at system 146 | startup 147 | 4.3 Run command "lspci | grep AMD" to check the BDF number 148 | of the AMD GPU device 149 | 4.4 Download amdgpu-pro driver from(TBD) 150 | ***** 151 | and intall the driver properly 152 | 4.5 Download xorg.conf file from(TBD) 153 | ***** 154 | to /etc/X11/xorg.conf.d, edit the following section in 155 | xorg.conf 156 | Section "Device" 157 | Identifier "Card0" 158 | Driver "amdgpu" 159 | BusID "PCI:xx:xx:xx" 160 | EndSection 161 | and change xx:xx:xx to the BDF number in step 3.3 162 | 4.6 Edit the grub configuration to enter console mode at system 163 | startup(this is recommended but not mandatory) 164 | 4.7 Reboot the guest system 165 | 4.8 Login guest system and run command "startx" (this 166 | should be skipped if step 4.6 is not done) 167 | 4.9 Connect the guest system through VNC remote desktop 168 | 169 | -------------------------------------------------------------------------------- /drv/gim_dma.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | 30 | #include "gim_dma.h" 31 | #include "gim_adapter.h" 32 | #include "gim_command.h" 33 | #include "gim_config.h" 34 | #include "gim_gpuiov.h" 35 | #include "gim_debug.h" 36 | #include "gim_os_service.h" 37 | 38 | #include "gim_s7150_reg.h" 39 | 40 | /* Quick define for 5msec in units of nsec to be used with timespec. */ 41 | #define FIVE_MSEC__IN_NSEC 5000000 42 | 43 | void *map_vf_fb(struct pci_dev *pdev); 44 | 45 | /* 46 | * The DMA FIFO can hold two DMA requests. 47 | * Check and wait until there is at least one free spot available 48 | */ 49 | static int wait_dma_ready(struct adapter *adapt) 50 | { 51 | struct timespec start_time; 52 | unsigned long dma_cntl = 0; 53 | int rc = 0; 54 | 55 | getnstimeofday(&start_time); 56 | do { 57 | dma_cntl = pf_read_register(adapt, mmCP_DMA_CNTL); 58 | /* DMA has 2 PIO commands in the FIFO 59 | * (top 2 bits are command count) 60 | */ 61 | } while ((dma_cntl & 0x80000000) 62 | && (time_elapsed(&start_time).tv_nsec 63 | < FIVE_MSEC__IN_NSEC)); /* Max 5 msec wait */ 64 | 65 | if (dma_cntl & 0x80000000) { 66 | gim_info("DMA failed to make room for another cmd after 5 msec\n"); 67 | gim_info(" dma_cntl = 0x%08lx\n", dma_cntl); 68 | rc = -1; 69 | } 70 | return rc; 71 | } 72 | 73 | /* 74 | * Assume: The CP DMA has the bandwidth of around 10 GBytes per second. 75 | * The time consumed is around 100 us for 1M bytes. Wait 5ms for safty. 76 | */ 77 | static int wait_dma_complete(struct adapter *adapt) 78 | { 79 | struct timespec start_time; 80 | unsigned int cp_stat = 0; 81 | int rc = 0; 82 | 83 | getnstimeofday(&start_time); 84 | do { 85 | cp_stat = pf_read_register(adapt, mmCP_STAT); 86 | } while ((cp_stat & 0x80400000)/* CP_BUSY or DMA_BUSY */ 87 | /* Max 5 msec wait */ 88 | && (time_elapsed(&start_time).tv_nsec < FIVE_MSEC__IN_NSEC)); 89 | 90 | if (cp_stat & 0x80400000) { 91 | gim_info("Timed out waiting for dma to finish.\n"); 92 | gim_info(" cp_stat = 0x%08x\n", cp_stat); 93 | rc = -2; 94 | } 95 | return rc; 96 | } 97 | 98 | /* 99 | * Fill a region of VRAM with a pattern. 100 | */ 101 | static int dma_fill(struct adapter *adapt, unsigned long long offset, 102 | unsigned long long size) 103 | { 104 | int rc = 0; 105 | unsigned int pattern = 0xdeadbeef; 106 | 107 | /* Make sure that there is room for a new DMA command */ 108 | rc = wait_dma_ready(adapt); 109 | if (rc) { 110 | gim_info("dma_fill() failed while waiting for dma_ready()\n"); 111 | return rc; 112 | } 113 | 114 | /* src = data, dst = das, dst_mtype = 3(uncacheable) */ 115 | pf_write_register(adapt, mmCP_DMA_PIO_CONTROL, 0x40c00c00); 116 | 117 | /* src: data(0) */ 118 | pf_write_register(adapt, mmCP_DMA_PIO_SRC_ADDR, pattern); 119 | pf_write_register(adapt, mmCP_DMA_PIO_SRC_ADDR_HI, 0); 120 | 121 | /* dst = offset */ 122 | pf_write_register(adapt, mmCP_DMA_PIO_DST_ADDR, 123 | (unsigned long) (offset & 0xffffffff)); 124 | pf_write_register(adapt, mmCP_DMA_PIO_DST_ADDR_HI, 125 | (unsigned long) ((offset >> 32) & 0xffffffff)); 126 | 127 | /* command: RAW_WAIT SAIC: 1(not inc) DAS: 0(memory) SAS: 1(register) 128 | * DIS_WC: 0 129 | */ 130 | pf_write_register(adapt, 131 | mmCP_DMA_PIO_COMMAND, 132 | 0x54000000 | (((unsigned long) size) & 0x1fffff)); 133 | 134 | return rc; 135 | } 136 | 137 | /* 138 | *dma_copy() - Copy a bunch of date from VRAM 139 | *@adapt: pointer to amdgpu_device 140 | *@src: source of the data 141 | *@dest: destination of the copy 142 | *@size: size of the data to be copied 143 | * return 0: success 144 | * -1: failure 145 | */ 146 | int dma_copy(struct adapter *adapt, unsigned long long src, 147 | unsigned long long dest, unsigned long long size) 148 | { 149 | int rc = 0; 150 | 151 | rc = wait_dma_ready(adapt); 152 | if (rc) { 153 | gim_info("dma_copy failed with rc=%d\n", rc); 154 | return rc; 155 | } 156 | 157 | /* src = sas, src_mtype = 3, dst = das, dst_mtype = 3(uncacheable) */ 158 | pf_write_register(adapt, mmCP_DMA_PIO_CONTROL, 0x00c00c00); 159 | 160 | /* src: data(0) */ 161 | pf_write_register(adapt, mmCP_DMA_PIO_SRC_ADDR, 162 | (unsigned long) (src & 0xffffffff)); 163 | pf_write_register(adapt, mmCP_DMA_PIO_SRC_ADDR_HI, 164 | (unsigned long) ((src >> 32) & 0xffffffff)); 165 | 166 | /* dst = offset */ 167 | pf_write_register(adapt, mmCP_DMA_PIO_DST_ADDR, 168 | (unsigned long) (dest & 0xffffffff)); 169 | pf_write_register(adapt, mmCP_DMA_PIO_DST_ADDR_HI, 170 | (unsigned long) ((dest >> 32) & 0xffffffff)); 171 | 172 | /* command: RAW_WAIT DAS: 0(memory) SAS: 0(memory) DIS_WC: 0 */ 173 | pf_write_register(adapt, mmCP_DMA_PIO_COMMAND, 174 | 0x40000000 | (unsigned long) size); 175 | 176 | return rc; 177 | } 178 | /* 179 | * Clear a region of FB memory using the following algorithm... 180 | * 181 | * Start by filling a 64 byte block at the start of the FB range with 182 | * a pattern (0x0 by default) and set the destination pointer to the end 183 | * of the block. 184 | * 185 | * Copy from the start of the block to the destination pointer which will 186 | * double the block size that has been cleared. Set the destination pointer 187 | * to the end of the block. On each iteration through the loop copy from the 188 | * start of the FB range to the destination while doubling the block size. 189 | * 190 | * After the block size is 1MB then do dma copies of 1MB at a time until 191 | * the limit is reached. 192 | */ 193 | int dma_clear(struct adapter *adapt, unsigned long long offset, 194 | unsigned long long size) 195 | { 196 | unsigned long long src_addr; 197 | unsigned long long dest_addr; 198 | unsigned long long block_size = 64; 199 | unsigned long long copied_size = 0; 200 | int rc = 0; 201 | 202 | /* 203 | * Get the MCAddr of the start of the PF Framebuffer 204 | * The VF Framebuffer will start at "PF_MCAddr + offset" in the 205 | * PF address space. 206 | */ 207 | unsigned long pf_mc_addr = pf_read_register(adapt, 208 | mmMC_VM_FB_LOCATION); 209 | 210 | /* 211 | * src_addr will always point to the beginning offset of the region 212 | * to clear (the 'seed' block) dest_addr will move through the region 213 | * as blocks are copied 214 | */ 215 | dest_addr = ((unsigned long long) (pf_mc_addr & 0xffff) << 24) + offset; 216 | src_addr = dest_addr; 217 | 218 | gim_info("Clear VRAM from 0x%08llx to 0x%08llx\n", 219 | offset, offset + size - 1); 220 | 221 | /* Establish first 64 byte patterned block ('seed' block) */ 222 | rc = dma_fill(adapt, dest_addr, block_size); 223 | if (rc) 224 | gim_warn("dma_fill() failed with rc = %d\n", rc); 225 | 226 | /* Advance the destination pointer by the filled region size. */ 227 | dest_addr += block_size; 228 | /* We have already copied the first block 229 | * by filling it with a pattern 230 | */ 231 | copied_size = block_size; 232 | 233 | /* If dma_fill failed it won't go into 'while' loop */ 234 | while (rc == 0 && copied_size < size) { 235 | /* Make sure we don't go past end of region */ 236 | if (copied_size + block_size > size) 237 | block_size = size - copied_size; 238 | 239 | rc = dma_copy(adapt, src_addr, dest_addr, block_size); 240 | 241 | dest_addr += block_size; 242 | copied_size += block_size; 243 | 244 | /* Block size is still less than 1MB */ 245 | if (block_size < 0x100000) 246 | /* double the block size for the next iteration */ 247 | block_size <<= 1; 248 | } 249 | wait_dma_complete(adapt); 250 | gim_info("dma_clear() - FB has been cleared by dma_copy.\n"); 251 | 252 | return rc; 253 | } 254 | -------------------------------------------------------------------------------- /drv/gim_monitor_tonga.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #ifndef _GPU_IOV_MODULE__MONITOR_TONGA_H 24 | #define _GPU_IOV_MODULE__MONITOR_TONGA_H 25 | 26 | #include "gim_monitor.h" 27 | 28 | #define PPSMC_MSG_SCLKDPM_GETENABLEDMASK (0x162) 29 | #define PPSMC_MSG_API_GETSCLKFREQUENCY (0x200) 30 | 31 | /* Thermal */ 32 | enum thermal_sensor_type { 33 | /* TCEN0 sensors */ 34 | GNB_TCEN_0, 35 | GNB_TCEN_1, 36 | GNB_TCEN_2, 37 | GNB_TCEN_3, 38 | GNB_TCEN_4, 39 | GNB_TCEN_5, 40 | GNB_TCEN_6, 41 | GNB_TCEN_7, 42 | GNB_TCON_GLOBAL, 43 | 44 | /* TCEN1 sensors */ 45 | GNB_TCEN1_0, 46 | GNB_TCEN1_1, 47 | GNB_TCEN1_2, 48 | GNB_TCEN1_3, 49 | GNB_TCEN1_4, 50 | GNB_TCEN1_5, 51 | GNB_TCEN1_6, 52 | GNB_TCEN1_7, 53 | 54 | /* TCEN2 sensors */ 55 | GNB_TCEN2_0, 56 | GNB_TCEN2_1, 57 | GNB_TCEN2_2, 58 | GNB_TCEN2_3, 59 | GNB_TCEN2_4, 60 | GNB_TCEN2_5, 61 | GNB_TCEN2_6, 62 | GNB_TCEN2_7, 63 | 64 | GNB_TCEN_0_MAX, 65 | GNB_TCEN_1_MAX, 66 | GNB_TCEN_2_MAX, 67 | 68 | TCEN_PWR_DN_STATUS, 69 | 70 | /* discrete GPUs */ 71 | TSS_CURRENT, /* TSS reading based on selection */ 72 | TSS_0, 73 | TSS_1, 74 | TSS_2, 75 | TSS_3, 76 | TSS_4, 77 | 78 | /* internal thermal temp replacing the TSS ones from SI */ 79 | ASIC_MAX, 80 | CTF, 81 | SW_CTF_LIMIT, 82 | HW_CTF_LIMIT, 83 | 84 | /* external thermal sensor */ 85 | LM63, /* typical discrete GPU external thermal controller */ 86 | 87 | /* estimated temperature readings (added for Trinity, Kaveri, Kabini) */ 88 | EST_CPU_0, 89 | EST_CPU_1, 90 | EST_CPU_2, 91 | EST_CPU_3, 92 | EST_CPU_4, 93 | EST_CPU_5, 94 | EST_GPU, 95 | 96 | /* Tahiti */ 97 | TMON_0_INT, /* internal thermal sensor in TMON itself */ 98 | TMON_1_INT, /* internal thermal sensor in TMON itself */ 99 | TMON_2_INT, /* internal thermal sensor in TMON itself */ 100 | 101 | TMON_0_RDIL0, 102 | TMON_0_RDIL1, 103 | TMON_0_RDIL2, 104 | TMON_0_RDIL3, 105 | TMON_0_RDIL4, 106 | TMON_0_RDIL5, 107 | TMON_0_RDIL6, 108 | TMON_0_RDIL7, 109 | 110 | TMON_0_RDIL8, 111 | TMON_0_RDIL9, 112 | TMON_0_RDIL10, 113 | TMON_0_RDIL11, 114 | 115 | /* Hawaii */ 116 | TMON_0_RDIL12, 117 | TMON_0_RDIL13, 118 | TMON_0_RDIL14, 119 | TMON_0_RDIL15, 120 | 121 | 122 | TMON_0_RDIR0, 123 | TMON_0_RDIR1, 124 | TMON_0_RDIR2, 125 | TMON_0_RDIR3, 126 | TMON_0_RDIR4, 127 | TMON_0_RDIR5, 128 | TMON_0_RDIR6, 129 | TMON_0_RDIR7, 130 | 131 | TMON_0_RDIR8, 132 | TMON_0_RDIR9, 133 | TMON_0_RDIR10, 134 | TMON_0_RDIR11, 135 | 136 | /* Hawaii */ 137 | TMON_0_RDIR12, 138 | TMON_0_RDIR13, 139 | TMON_0_RDIR14, 140 | TMON_0_RDIR15, 141 | 142 | TMON_1_RDIL0, 143 | TMON_1_RDIL1, 144 | TMON_1_RDIL2, 145 | TMON_1_RDIL3, 146 | TMON_1_RDIL4, 147 | TMON_1_RDIL5, 148 | TMON_1_RDIL6, 149 | TMON_1_RDIL7, 150 | 151 | /* Hawaii */ 152 | TMON_1_RDIL8, 153 | TMON_1_RDIL9, 154 | TMON_1_RDIL10, 155 | TMON_1_RDIL11, 156 | TMON_1_RDIL12, 157 | TMON_1_RDIL13, 158 | TMON_1_RDIL14, 159 | TMON_1_RDIL15, 160 | 161 | TMON_1_RDIR0, 162 | TMON_1_RDIR1, 163 | TMON_1_RDIR2, 164 | TMON_1_RDIR3, 165 | TMON_1_RDIR4, 166 | TMON_1_RDIR5, 167 | TMON_1_RDIR6, 168 | TMON_1_RDIR7, 169 | 170 | /* Hawaii */ 171 | TMON_1_RDIR8, 172 | TMON_1_RDIR9, 173 | TMON_1_RDIR10, 174 | TMON_1_RDIR11, 175 | TMON_1_RDIR12, 176 | TMON_1_RDIR13, 177 | TMON_1_RDIR14, 178 | TMON_1_RDIR15, 179 | 180 | /* fiji */ 181 | TMON_2_RDIL0, 182 | TMON_2_RDIL1, 183 | TMON_2_RDIL2, 184 | TMON_2_RDIL3, 185 | TMON_2_RDIL4, 186 | TMON_2_RDIL5, 187 | TMON_2_RDIL6, 188 | TMON_2_RDIL7, 189 | 190 | TMON_2_RDIL8, 191 | TMON_2_RDIL9, 192 | TMON_2_RDIL10, 193 | TMON_2_RDIL11, 194 | TMON_2_RDIL12, 195 | TMON_2_RDIL13, 196 | TMON_2_RDIL14, 197 | TMON_2_RDIL15, 198 | 199 | TMON_2_RDIR0, 200 | TMON_2_RDIR1, 201 | TMON_2_RDIR2, 202 | TMON_2_RDIR3, 203 | TMON_2_RDIR4, 204 | TMON_2_RDIR5, 205 | TMON_2_RDIR6, 206 | TMON_2_RDIR7, 207 | 208 | TMON_2_RDIR8, 209 | TMON_2_RDIR9, 210 | TMON_2_RDIR10, 211 | TMON_2_RDIR11, 212 | TMON_2_RDIR12, 213 | TMON_2_RDIR13, 214 | TMON_2_RDIR14, 215 | TMON_2_RDIR15, 216 | 217 | /* TMON thermal gradient */ 218 | TMON_GRADIENT, /* M2E */ 219 | TMON_GRADIENT_M2M, 220 | 221 | /* DTE temperature */ 222 | DTE, 223 | 224 | /* RDI reading corresponding to CTF */ 225 | CTF_RDI, 226 | 227 | /* memory chip temperature */ 228 | HBM_STACK0, 229 | HBM_STACK1, 230 | HBM_STACK2, 231 | HBM_STACK3, 232 | 233 | /* unknown/invalid */ 234 | TSS_UNKNOWN 235 | }; 236 | 237 | 238 | union cg_mult_thermal_ctrl { 239 | struct { 240 | #if defined(LITTLEENDIAN_CPU) 241 | unsigned int ts_filter : 4; 242 | unsigned int unused : 5; 243 | unsigned int thermal_range_rst : 1; 244 | unsigned int : 10; 245 | unsigned int temp_sel : 8; 246 | unsigned int thm_ready_clear : 1; 247 | unsigned int : 3; 248 | #elif defined(BIGENDIAN_CPU) 249 | unsigned int : 3; 250 | unsigned int thm_ready_clear : 1; 251 | unsigned int temp_sel : 8; 252 | unsigned int : 10; 253 | unsigned int thermal_range_rst : 1; 254 | unsigned int unused : 5; 255 | unsigned int ts_filter : 4; 256 | #endif 257 | } bitfields, bits; 258 | unsigned int u32all; 259 | signed int i32all; 260 | float f32all; 261 | }; 262 | 263 | union thm_tmon0_rdil0_data { 264 | struct { 265 | #if defined(LITTLEENDIAN_CPU) 266 | unsigned int z : 11; 267 | unsigned int valid : 1; 268 | unsigned int temp : 12; 269 | unsigned int : 8; 270 | #elif defined(BIGENDIAN_CPU) 271 | unsigned int : 8; 272 | unsigned int temp : 12; 273 | unsigned int valid : 1; 274 | unsigned int z : 11; 275 | #endif 276 | } bitfields, bits; 277 | unsigned int u32all; 278 | signed int i32all; 279 | float f32all; 280 | }; 281 | 282 | #define AMDGIM_POWER_DELAY_MS 100 283 | 284 | #define ixS0_VID_SMIO_CNTL 0xC06001E4 285 | #define ixPWR_SVI2_STATUS 0xC0200294 286 | 287 | union pwr_svi2_status { 288 | struct { 289 | #if defined(LITTLEENDIAN_CPU) 290 | unsigned int plane1_vid : 8; 291 | unsigned int plane2_vid : 8; 292 | unsigned int vid_change_busy : 1; 293 | unsigned int svi2_busy : 1; 294 | unsigned int delay_cnt_busy : 1; 295 | unsigned int : 13; 296 | #elif defined(BIGENDIAN_CPU) 297 | unsigned int : 13; 298 | unsigned int delay_cnt_busy : 1; 299 | unsigned int svi2_busy : 1; 300 | unsigned int vid_change_busy : 1; 301 | unsigned int plane2_vid : 8; 302 | unsigned int plane1_vid : 8; 303 | #endif 304 | } bitfields, bits; 305 | unsigned int u32all; 306 | signed int i32all; 307 | float f32all; 308 | }; 309 | 310 | /* SMC */ 311 | #define SMC_WAIT_TICK_MS 10 312 | #define SMC_WAIT_TIMEOUT_MS (1 * 1000) 313 | 314 | union smc_msg_arg_1 { 315 | struct { 316 | #if defined(LITTLEENDIAN_CPU) 317 | unsigned int smc_msg_arg : 32; 318 | #elif defined(BIGENDIAN_CPU) 319 | unsigned int smc_msg_arg : 32; 320 | #endif 321 | } bitfields, bits; 322 | unsigned int u32all; 323 | signed int i32all; 324 | float f32all; 325 | }; 326 | 327 | union smc_message_1 { 328 | struct { 329 | #if defined(LITTLEENDIAN_CPU) 330 | unsigned int smc_msg : 16; 331 | unsigned int : 16; 332 | #elif defined(BIGENDIAN_CPU) 333 | unsigned int : 16; 334 | unsigned int smc_msg : 16; 335 | #endif 336 | } bitfields, bits; 337 | unsigned int u32all; 338 | signed int i32all; 339 | float f32all; 340 | }; 341 | 342 | union smc_resp_1 { 343 | struct { 344 | #if defined(LITTLEENDIAN_CPU) 345 | unsigned int smc_resp : 16; 346 | unsigned int : 16; 347 | #elif defined(BIGENDIAN_CPU) 348 | unsigned int : 16; 349 | unsigned int smc_resp : 16; 350 | #endif 351 | } bitfields, bits; 352 | unsigned int u32all; 353 | signed int i32all; 354 | float f32all; 355 | }; 356 | 357 | #endif 358 | -------------------------------------------------------------------------------- /drv/gim_fb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | 29 | #include "gim_fb.h" 30 | #include "gim_adapter.h" 31 | #include "gim_command.h" 32 | #include "gim_config.h" 33 | #include "gim_gpuiov.h" 34 | #include "gim_debug.h" 35 | #include "gim_dma.h" 36 | 37 | 38 | int init_context_save_area(struct adapter *adapt, kcl_type_u64 base, 39 | kcl_type_u64 size) 40 | { 41 | gim_info("AMD GIM init_context_save_area: base =%llx size=%llx.\n", 42 | base, size); 43 | 44 | set_gpuiov_context(adapt->pf.pci_dev, &adapt->gpuiov, size, 45 | PCI_GPUIOV_CNTXT__LOC_IN_FB, 46 | base); 47 | return 0; 48 | } 49 | 50 | int init_pf_fb(struct adapter *adapt, kcl_type_u64 size) 51 | { 52 | /* PF occupies the frame buffer always starting from 0. */ 53 | adapt->partition[PF_INDEX].slot.base = 0; 54 | adapt->partition[PF_INDEX].slot.size = size; 55 | 56 | adapt->pf.fb_partition = &adapt->partition[PF_INDEX]; 57 | 58 | /* Programming total_fb_consumed in GPUIOV. */ 59 | gim_info("total framebuffer available = %x\n", 60 | adapt->gpuiov.total_fb_available); 61 | gim_info("pf framebuffer = %llx\n", size); 62 | gim_info("total framebuffer consumed = %llx\n", 63 | adapt->gpuiov.total_fb_available - size); 64 | set_gpuiov_total_fb_consumed(adapt->pf.pci_dev, &adapt->gpuiov, 65 | adapt->gpuiov.total_fb_available - size); 66 | return 0; 67 | } 68 | 69 | void init_vf_fb(struct adapter *adapt, struct function *func) 70 | { 71 | /* Convert from GPUIOV values to byte values */ 72 | unsigned long long fb_offset = func->fb_partition->slot.base << 20; 73 | unsigned long long fb_size = func->fb_partition->slot.size << 20; 74 | 75 | gim_info("init_vf_fb(fb_offset = 0x%08llx, size=0x%08llx\n", fb_offset, 76 | fb_size); 77 | dma_clear(adapt, fb_offset, fb_size); 78 | } 79 | 80 | int init_fb_dynamic(struct adapter *adapt, kcl_type_u64 base, 81 | kcl_type_u64 total_size) 82 | { 83 | struct slot_list_node *slot; 84 | struct partition *partition; 85 | kcl_type_u32 i, j; 86 | 87 | slot = vmalloc(sizeof(struct slot_list_node)); 88 | slot->slot.base = base; 89 | slot->slot.size = total_size; 90 | slot->next = NULL; 91 | 92 | adapt->max_fb_slot = total_size; 93 | adapt->empty_slot_list = slot; 94 | mutex_init(&adapt->fb_dynamic_alloc_mutex); 95 | 96 | partition = &adapt->partition[VF0_INDEX]; 97 | for (i = 0 ; i < adapt->total_vfs ; ++i) { 98 | partition->slot.base = 0; 99 | partition->slot.size = 0; 100 | 101 | for (j = 0; j < adapt->total_vfs; j++) { 102 | if (adapt->vfs[j].func_id == i) 103 | adapt->vfs[j].fb_partition = partition; 104 | } 105 | partition++; 106 | } 107 | return 0; 108 | } 109 | 110 | int get_fb_size_static(struct adapter *adapter, u32 *num_vf, u64 base, 111 | u64 total_size, u64 min_size) 112 | { 113 | u32 new_count; 114 | u32 vf_fb_size; 115 | 116 | if (get_vf_fb_option() == VF_FB__DEFAULT) { 117 | vf_fb_size = rounddown(total_size / *num_vf, FB__SIZE_IN_16M); 118 | if (vf_fb_size < min_size) { 119 | // Not enough memory to support all vfs. 120 | *num_vf = total_size / min_size; 121 | vf_fb_size = rounddown(min_size, FB__SIZE_IN_16M); 122 | } 123 | } else { 124 | vf_fb_size = get_vf_fb_option(); 125 | gim_info("VF FB size specified as %dMB, min_size = %lld\n", 126 | vf_fb_size, min_size); 127 | if (vf_fb_size < min_size) 128 | vf_fb_size = min_size; 129 | new_count = total_size / vf_fb_size; 130 | if (new_count < *num_vf) 131 | *num_vf = new_count; 132 | vf_fb_size = rounddown(vf_fb_size, FB__SIZE_IN_16M); 133 | } 134 | 135 | return vf_fb_size; 136 | } 137 | 138 | int init_fb_static(struct adapter *adapt, kcl_type_u32 num_vf, 139 | kcl_type_u64 base, kcl_type_u64 total_size, 140 | kcl_type_u64 min_size) 141 | { 142 | kcl_type_u32 i, j; 143 | struct partition *partition; 144 | 145 | gim_info("AMD GIM init_fb_static: num_vf = %d, base= %lld, total_size=%lld, min_size=%lld\n", 146 | num_vf, base, total_size, min_size); 147 | if (num_vf > 0) { 148 | kcl_type_u32 vf_fb_size; 149 | kcl_type_u32 vf_avg_fb_size; 150 | 151 | vf_avg_fb_size = rounddown(total_size / num_vf, 152 | FB__SIZE_IN_16M); 153 | if (get_vf_fb_option() == VF_FB__DEFAULT) { 154 | vf_fb_size = vf_avg_fb_size; 155 | } else { 156 | vf_fb_size = get_vf_fb_option(); 157 | gim_info("VF FB size specified as %dMB, min_size = %lld\n", 158 | vf_fb_size, min_size); 159 | if (vf_fb_size < min_size) 160 | vf_fb_size = min_size; 161 | 162 | if (vf_fb_size > vf_avg_fb_size) 163 | vf_fb_size = vf_avg_fb_size; 164 | } 165 | 166 | gim_info("AMD GIM init_fb_static: vf_fb_size = %d, base= %lld\n", 167 | vf_fb_size, base); 168 | 169 | adapt->max_fb_slot = vf_fb_size; 170 | 171 | partition = &adapt->partition[VF0_INDEX]; 172 | for (i = 0 ; i < num_vf ; ++i) { 173 | partition->slot.base = base; 174 | partition->slot.size = vf_fb_size; 175 | 176 | gim_info("AMD GIM init_fb_static: partition %d base =%lld,size= %lld\n", 177 | i, partition->slot.base, 178 | partition->slot.size); 179 | 180 | base += vf_fb_size; 181 | 182 | set_gpuiov_vf_frame_buffer(adapt->pf.pci_dev, 183 | &adapt->gpuiov, i, 184 | partition->slot.size, 185 | partition->slot.base); 186 | 187 | for (j = 0; j < adapt->total_vfs; j++) { 188 | if (adapt->vfs[j].func_id == i) 189 | adapt->vfs[j].fb_partition = partition; 190 | } 191 | partition++; 192 | } 193 | } 194 | return 0; 195 | } 196 | 197 | int init_frame_buffer_partition(struct adapter *adapt) 198 | { 199 | kcl_type_u64 max_fb_size; 200 | kcl_type_u64 max_pf_fb_size; 201 | kcl_type_u64 mini_pf_fb_size; 202 | kcl_type_u64 mini_vf_fb_size; 203 | kcl_type_u64 csa_base; 204 | kcl_type_u64 vf_fb_base; 205 | kcl_type_u64 pf_fb_size; 206 | kcl_type_u64 vf_fb_size; 207 | struct resource *res; 208 | 209 | res = &adapt->pf.pci_dev->resource[BAR__FRAME_BUFFER]; 210 | mini_pf_fb_size = TO_MBYTES(res->end - res->start + 1); 211 | /* 212 | * If large bar is enabled, PF does not work as vga device. 213 | * Set minimal pf fb to be 16M bytes. 214 | */ 215 | if (mini_pf_fb_size >= adapt->gpuiov.total_fb_available) 216 | mini_pf_fb_size = 16; 217 | 218 | gim_info("PCI defined PF FB size = %lld MB\n", mini_pf_fb_size); 219 | 220 | res = &adapt->vfs[0].pci_dev->resource[BAR__FRAME_BUFFER]; 221 | mini_vf_fb_size = TO_MBYTES(res->end - res->start + 1); 222 | gim_info("PCI defined VF FB size = %lld MB\n", mini_vf_fb_size); 223 | max_fb_size = rounddown(adapt->gpuiov.total_fb_available - 224 | roundup(FB__RESERVED_CSA_IN_1M, FB__SIZE_IN_16M), 225 | FB__SIZE_IN_16M); 226 | gim_info("Total FB Available = %d MB, CSA = %d MB\n", 227 | adapt->gpuiov.total_fb_available, FB__RESERVED_CSA_IN_1M); 228 | gim_info("Max Remaining FB Size = %lld\n", max_fb_size); 229 | /* Validate the PF frame buffer size */ 230 | pf_fb_size = (kcl_type_u64)get_pf_fb_option(); 231 | if (pf_fb_size <= mini_pf_fb_size) 232 | pf_fb_size = mini_pf_fb_size; 233 | 234 | max_pf_fb_size = max_fb_size 235 | - adapt->enabled_vfs 236 | * roundup(mini_vf_fb_size, FB__SIZE_IN_16M); 237 | if (pf_fb_size > max_pf_fb_size) 238 | pf_fb_size = max_pf_fb_size; 239 | 240 | gim_info("PF FB size after checking limits from config file = %lldMB\n", 241 | pf_fb_size); 242 | pf_fb_size = rounddown(pf_fb_size, FB__SIZE_IN_16M); 243 | gim_info("PF rounded down to nearest 16MB boundary = %lld\n", 244 | pf_fb_size); 245 | 246 | /* Init the PF frame buffer. */ 247 | init_pf_fb(adapt, pf_fb_size); 248 | 249 | /* CSA is reserved at top of the frame buffer. */ 250 | csa_base = pf_fb_size; 251 | gim_info("CSA starts at offset %lldMB\n", csa_base); 252 | init_context_save_area(adapt, pf_fb_size, FB__CSA_SIZE_IN_256K); 253 | 254 | /* VFs FB follows PF FB, starting from vf_fb_size */ 255 | vf_fb_base = roundup(csa_base + FB__RESERVED_CSA_IN_1M, 256 | FB__SIZE_IN_16M); 257 | gim_info("VF FB base = %lldMB (%lld + %d)\n", vf_fb_base, csa_base, 258 | roundup(FB__RESERVED_CSA_IN_1M, FB__SIZE_IN_16M)); 259 | 260 | vf_fb_size = rounddown(max_fb_size - pf_fb_size, FB__SIZE_IN_16M); 261 | gim_info("VF FB Size = %lldMB (%lld - %lld)\n", vf_fb_size, max_fb_size, 262 | pf_fb_size); 263 | 264 | /* save it for monitoring use */ 265 | adapt->vf_fb_base = vf_fb_base; 266 | adapt->vf_fb_size = vf_fb_size; 267 | 268 | if (get_fb_partition_option() == FB_PARTITION__STATIC) { 269 | init_fb_static(adapt, adapt->enabled_vfs, vf_fb_base, 270 | vf_fb_size, mini_vf_fb_size); 271 | adapt->available_vfs = adapt->enabled_vfs; 272 | } else if (get_fb_partition_option() == FB_PARTITION__DYNAMIC) { 273 | init_fb_dynamic(adapt, vf_fb_base, vf_fb_size); 274 | } else { 275 | return -1; 276 | } 277 | 278 | return 0; 279 | } 280 | 281 | -------------------------------------------------------------------------------- /drv/gim_flr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "gim_debug.h" 28 | #include "gim_flr.h" 29 | #include "gim_adapter.h" 30 | #include "gim_pci_config.h" 31 | #include "gim_interface.h" 32 | #include "gim_kcl_pci.h" 33 | #include "gim_kcl_os.h" 34 | #include "gim_os_service.h" 35 | #include "gim_s7150_reg.h" 36 | 37 | static void save_msi_regs(struct pci_dev *dev, unsigned char *p) 38 | { 39 | int msi_loc, i; 40 | kcl_type_u8 data_8; 41 | 42 | msi_loc = pci_find_capability(dev, PCI_CAP_ID_MSI); 43 | if (msi_loc) { 44 | for (i = 0; i <= 0xf; i++) { 45 | pci_read_config_byte(dev, msi_loc + i, &data_8); 46 | *(p + msi_loc + i) = data_8; 47 | } 48 | } else 49 | gim_info("can't find msi cap!\n"); 50 | } 51 | 52 | static void restore_msi_regs(struct pci_dev *dev, unsigned char *p) 53 | { 54 | int msi_loc, i; 55 | kcl_type_u8 data_8; 56 | 57 | msi_loc = pci_find_capability(dev, PCI_CAP_ID_MSI); 58 | if (msi_loc) { 59 | for (i = 0; i <= 0xf; i++) { 60 | data_8 = *(p + msi_loc + i); 61 | pci_write_config_byte(dev, msi_loc + i, data_8); 62 | } 63 | } else 64 | gim_info("can't find msi cap!\n"); 65 | } 66 | 67 | static void save_scratch_memory(struct adapter *adapt, unsigned int *dest, 68 | unsigned int addrReg, unsigned int dataReg, 69 | unsigned int offset, unsigned int length) 70 | { 71 | unsigned int index = offset; 72 | 73 | for (index = offset; index < offset + length; index++) { 74 | pf_write_register(adapt, addrReg, index); 75 | *dest = pf_read_register(adapt, dataReg); 76 | dest++; 77 | } 78 | } 79 | 80 | static void restore_scratch_memory(struct adapter *adapt, unsigned int *src, 81 | unsigned int addrReg, unsigned int dataReg, 82 | unsigned int offset, unsigned int length) 83 | { 84 | unsigned int index = offset; 85 | 86 | for (index = offset; index < offset + length; index++) { 87 | pf_write_register(adapt, addrReg, index); 88 | pf_write_register(adapt, dataReg, src[index]); 89 | } 90 | } 91 | 92 | int gim_save_cpc_state(struct adapter *adapt, unsigned int *cp_cpc_ic) 93 | { 94 | cp_cpc_ic[0] = pf_read_register(adapt, mmCP_CPC_IC_BASE_LO); 95 | cp_cpc_ic[1] = pf_read_register(adapt, mmCP_CPC_IC_BASE_HI); 96 | cp_cpc_ic[2] = pf_read_register(adapt, mmCP_CPC_IC_BASE_CNTL); 97 | 98 | return 0; 99 | } 100 | 101 | int gim_restore_cpc_state(struct adapter *adapt, unsigned int *cp_cpc_ic) 102 | { 103 | pf_write_register(adapt, mmCP_CPC_IC_BASE_LO, cp_cpc_ic[0]); 104 | pf_write_register(adapt, mmCP_CPC_IC_BASE_HI, cp_cpc_ic[1]); 105 | pf_write_register(adapt, mmCP_CPC_IC_BASE_CNTL, cp_cpc_ic[2]); 106 | 107 | gim_info("CPC state is restored to addr: 0x%x%x ctrl: 0x%x\n", 108 | cp_cpc_ic[1], cp_cpc_ic[0], cp_cpc_ic[2]); 109 | 110 | return 0; 111 | } 112 | 113 | int gim_save_vddgfx_state(struct adapter *adapt, struct function *vf) 114 | { 115 | save_rlcv_state(vf); 116 | gim_info("RLCV responced SAVE_RLCV_STATE\n"); 117 | 118 | /* re-locate the scrach addr */ 119 | while (pf_read_register(adapt, mmRLC_GPU_IOV_SCRATCH_ADDR) != 0) 120 | pf_read_register(adapt, mmRLC_GPU_IOV_SCRATCH_DATA); 121 | 122 | gim_info("mmRLC_GPU_IOV_SCRATCH_ADDR = %x\n", 123 | pf_read_register(adapt, mmRLC_GPU_IOV_SCRATCH_ADDR)); 124 | save_scratch_memory(adapt, 125 | adapt->rlcv_scratch[vf->func_id], 126 | mmRLC_GPU_IOV_SCRATCH_ADDR, 127 | mmRLC_GPU_IOV_SCRATCH_DATA, 128 | 0, 129 | 256); 130 | gim_info("RLCV scratch saved\n"); 131 | 132 | return 0; 133 | } 134 | 135 | static int gim_restore_vddgfx_state(struct adapter *adapt, struct function *vf) 136 | { 137 | kcl_type_u32 rlc_iov_cntl, rlc_cntl; 138 | 139 | pf_write_register(adapt, mmRLC_GPM_THREAD_ENABLE, 0xf); 140 | 141 | /* Re-enable rlcv first */ 142 | rlc_iov_cntl = pf_read_register(adapt, mmRLC_GPU_IOV_F32_CNTL); 143 | rlc_iov_cntl = REG_SET_FIELD(rlc_iov_cntl, 144 | RLC_GPU_IOV_F32_CNTL, 145 | ENABLE, 146 | 1); 147 | pf_write_register(adapt, mmRLC_GPU_IOV_F32_CNTL, rlc_iov_cntl); 148 | gim_info("RLC_V enabled\n"); 149 | 150 | /* Re-enable RLC */ 151 | rlc_cntl = pf_read_register(adapt, mmRLC_CNTL); 152 | rlc_cntl = REG_SET_FIELD(rlc_cntl, RLC_CNTL, RLC_ENABLE_F32, 1); 153 | pf_write_register(adapt, mmRLC_CNTL, rlc_cntl); 154 | gim_info("RLC_G enabled\n"); 155 | 156 | while (pf_read_register(adapt, mmRLC_GPU_IOV_SCRATCH_ADDR) != 0x0) 157 | pf_read_register(adapt, mmRLC_GPU_IOV_SCRATCH_DATA); 158 | 159 | gim_info("mmRLC_GPU_IOV_SCRATCH_ADDR = %x\n", 160 | pf_read_register(adapt, mmRLC_GPU_IOV_SCRATCH_ADDR)); 161 | restore_scratch_memory(adapt, 162 | adapt->rlcv_scratch[vf->func_id], 163 | mmRLC_GPU_IOV_SCRATCH_ADDR, 164 | mmRLC_GPU_IOV_SCRATCH_DATA, 165 | 0, 166 | 0x29); 167 | 168 | while (pf_read_register(adapt, mmRLC_GPU_IOV_SCRATCH_ADDR) != 0xb0) 169 | pf_read_register(adapt, mmRLC_GPU_IOV_SCRATCH_DATA); 170 | 171 | gim_info("mmRLC_GPU_IOV_SCRATCH_ADDR = %x\n", 172 | pf_read_register(adapt, mmRLC_GPU_IOV_SCRATCH_ADDR)); 173 | restore_scratch_memory(adapt, 174 | adapt->rlcv_scratch[vf->func_id], 175 | mmRLC_GPU_IOV_SCRATCH_ADDR, 176 | mmRLC_GPU_IOV_SCRATCH_DATA, 177 | 0xb0, 178 | 0x1f); 179 | 180 | load_rlcv_state(vf); 181 | gim_info("RLCV response LOAD_RLCV_STATE\n"); 182 | 183 | return 0; 184 | } 185 | 186 | static int gim_enable_flr(struct adapter *adapt) 187 | { 188 | unsigned int reg_val = 0; 189 | 190 | /* Program ixPCI_STRAP_MISC::STRAP_FLR_EN = 1 */ 191 | pf_write_register(adapt, mmPCIE_INDEX, ixPCIE_STRAP_MISC); 192 | reg_val = pf_read_register(adapt, mmPCIE_DATA); 193 | gim_info("Read PCIE_STRAP_MISC = 0x%x\n", reg_val); 194 | reg_val |= PCIE_STRAP_MISC__STRAP_FLR_EN_MASK; 195 | pf_write_register(adapt, mmPCIE_DATA, reg_val); 196 | gim_info("Write PCIE_STRAP_MISC = 0x%x\n", reg_val); 197 | 198 | /* Program ixSWRST_EP_CONTROL_0::EP_FLR0_REST_EN = 1 */ 199 | pf_write_register(adapt, mmPCIE_INDEX, ixSWRST_EP_CONTROL_0); 200 | reg_val = pf_read_register(adapt, mmPCIE_DATA); 201 | gim_info("Read SWRST_EP_CONTROL_0 = 0x0%x\n", reg_val); 202 | reg_val |= SWRST_EP_COMMAND_0__EP_FLR0_RESET_MASK; 203 | reg_val |= SWRST_EP_CONTROL_0__EP_FLR_DISABLE_CFG_RST_MASK; 204 | pf_write_register(adapt, mmPCIE_DATA, reg_val); 205 | gim_info("Write SWRST_EP_CONTROL_0 = 0x%x\n", reg_val); 206 | 207 | return 0; 208 | } 209 | 210 | static int gim_save_flr_state(struct adapter *adapt, struct function *vf) 211 | { 212 | unsigned int idx = 0; 213 | unsigned int *pci_cfg = NULL; 214 | 215 | /* Save the vf pci cfg space */ 216 | pci_cfg = (unsigned int *)(&vf->flr_state.pci_cfg); 217 | for (idx = 0; idx < VF_FLR_PCI_CONFIG_SIZE; idx += 4) { 218 | kcl_pci_read_config_dword(vf->pci_dev, idx, pci_cfg); 219 | pci_cfg++; 220 | } 221 | 222 | save_msi_regs(vf->pci_dev, (unsigned char *)&vf->flr_state.pci_cfg); 223 | 224 | /* Save PCIE_STRAP_MISC */ 225 | pf_write_register(adapt, mmPCIE_INDEX, ixPCIE_STRAP_MISC); 226 | vf->flr_state.pcie_strap_misc = pf_read_register(adapt, mmPCIE_DATA); 227 | gim_info("Read PCIE_STRAP_MISC = 0x%x\n", 228 | vf->flr_state.pcie_strap_misc); 229 | 230 | /* Save SWRST_EP_CONTROL_0 */ 231 | pf_write_register(adapt, mmPCIE_INDEX, ixSWRST_EP_CONTROL_0); 232 | vf->flr_state.swrst_ep_control_0 = pf_read_register(adapt, 233 | mmPCIE_DATA); 234 | gim_info("Read SWRST_EP_CONTROL_0 = 0x%x\n", 235 | vf->flr_state.swrst_ep_control_0); 236 | 237 | return 0; 238 | } 239 | 240 | static int gim_restore_flr_state(struct adapter *adapt, struct function *vf) 241 | { 242 | unsigned int idx = 0; 243 | unsigned int *pci_cfg = NULL; 244 | 245 | /* Restore the vf pci cfg space */ 246 | pci_cfg = (unsigned int *)(&vf->flr_state.pci_cfg); 247 | for (idx = 0; idx < VF_FLR_PCI_CONFIG_SIZE; idx += 4) { 248 | kcl_pci_write_config_dword(vf->pci_dev, idx, *pci_cfg); 249 | pci_cfg++; 250 | } 251 | 252 | restore_msi_regs(vf->pci_dev, (unsigned char *)&vf->flr_state.pci_cfg); 253 | 254 | /* Restore PCIE_STRAP_MISC */ 255 | pf_write_register(adapt, mmPCIE_INDEX, ixPCIE_STRAP_MISC); 256 | pf_write_register(adapt, mmPCIE_DATA, vf->flr_state.pcie_strap_misc); 257 | gim_info("Write PCIE_STRAP_MISC = 0x%x\n", 258 | vf->flr_state.pcie_strap_misc); 259 | 260 | /* Restore SWRST_EP_CONTROL_0 */ 261 | pf_write_register(adapt, mmPCIE_INDEX, ixSWRST_EP_CONTROL_0); 262 | pf_write_register(adapt, mmPCIE_DATA, 263 | vf->flr_state.swrst_ep_control_0); 264 | gim_info("Write SWRST_EP_CONTROL_0 = 0x%x\n", 265 | vf->flr_state.swrst_ep_control_0); 266 | 267 | return 0; 268 | } 269 | 270 | int gim_function_level_reset(struct adapter *adapt, struct function *vf) 271 | { 272 | int pos = 0; 273 | kcl_type_u16 val = 0; 274 | /* Wait at least 100ms for vf_flr complete*/ 275 | 276 | 277 | /* Enable vf flr */ 278 | gim_enable_flr(adapt); 279 | 280 | pos = kcl_pci_find_capability(vf->pci_dev, PCI_CAP_ID_EXP); 281 | if (pos) { 282 | kcl_pci_disable_bus_master(vf->pci_dev); 283 | kcl_pci_read_config_word(vf->pci_dev, 284 | pos + PCI_EXP_DEVCTL, 285 | &val); 286 | gim_info("Read 0x%x @pos = 0x%x\n", 287 | val, (pos + PCI_EXP_DEVCTL)); 288 | 289 | val |= PCI_EXP_DEVCTL_BCR_FLR; 290 | kcl_pci_write_config_word(vf->pci_dev, 291 | pos + PCI_EXP_DEVCTL, 292 | val); 293 | gim_info("Write 0x%x @pos = 0x%x\n", 294 | val, (pos + PCI_EXP_DEVCTL)); 295 | 296 | kcl_thread_sleep(100 * 1000); 297 | kcl_pci_enable_bus_master(vf->pci_dev); 298 | } else { 299 | gim_info("No PCIE CAPs found\n"); 300 | return -1; 301 | } 302 | return 0; 303 | } 304 | 305 | int gim_vf_flr(struct adapter *adapt, struct function *vf) 306 | { 307 | unsigned int sdma0_gfx_doorbell; 308 | unsigned int sdma1_gfx_doorbell; 309 | unsigned int rlc_cgcg_cgls_ctrl; 310 | unsigned int cp_cpc_ic[4]; 311 | 312 | rlc_cgcg_cgls_ctrl = pf_read_register(adapt, mmRLC_CGCG_CGLS_CTRL); 313 | 314 | sdma0_gfx_doorbell = pf_read_register(adapt, mmSDMA0_GFX_DOORBELL); 315 | sdma0_gfx_doorbell &= ~SDMA0_GFX_DOORBELL__CAPTURED_MASK; 316 | sdma1_gfx_doorbell = pf_read_register(adapt, mmSDMA1_GFX_DOORBELL); 317 | sdma1_gfx_doorbell &= ~SDMA1_GFX_DOORBELL__CAPTURED_MASK; 318 | 319 | gim_save_cpc_state(adapt, cp_cpc_ic); 320 | 321 | /* save FLR state */ 322 | gim_save_flr_state(adapt, vf); 323 | 324 | do_gettimeofday(&vf->time_log.reset_time); 325 | vf->time_log.reset_count++; 326 | 327 | /* do the FLR */ 328 | if (gim_function_level_reset(adapt, vf) != 0) { 329 | gim_info("FLR fails\n"); 330 | return -1; 331 | } 332 | 333 | /* restore FLR state */ 334 | gim_restore_flr_state(adapt, vf); 335 | 336 | gim_restore_vddgfx_state(adapt, vf); 337 | 338 | gim_restore_cpc_state(adapt, cp_cpc_ic); 339 | 340 | pf_write_register(adapt, mmRLC_CGCG_CGLS_CTRL, rlc_cgcg_cgls_ctrl); 341 | pf_write_register(adapt, mmSDMA0_GFX_DOORBELL, sdma0_gfx_doorbell); 342 | pf_write_register(adapt, mmSDMA1_GFX_DOORBELL, sdma1_gfx_doorbell); 343 | 344 | return 0; 345 | } 346 | 347 | -------------------------------------------------------------------------------- /drv/gim_config.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "gim_command.h" 30 | #include "gim_debug.h" 31 | 32 | /* Options defined in configure file */ 33 | struct config_option { 34 | const char *name; 35 | int value; 36 | const int min; 37 | const int max; 38 | }; 39 | 40 | enum option_index { 41 | CONFIG_OPTION__START = 0, 42 | CONFIG_OPTION__FB = CONFIG_OPTION__START, 43 | CONFIG_OPTION__SCHEDULER, 44 | CONFIG_OPTION__VF_NUMBER, 45 | CONFIG_OPTION__PF_FB_SIZE, 46 | CONFIG_OPTION__VF_FB_SIZE, 47 | CONFIG_OPTION__SCHED_INTERVAL, 48 | CONFIG_OPTION__SCHED_INTERVAL_US, 49 | CONFIG_OPTION__FB_CLEAR, 50 | CONFIG_OPTION__MAX 51 | }; 52 | 53 | struct config_option config_options[] = { 54 | 55 | {FB_OPTION__KEY, FB_PARTITION__DEFAULT, 56 | FB_PARTITION__START, FB_PARTITION__MAX}, 57 | 58 | {SCHEDULE_OPTION__KEY, SCHEDULER__DEFAULT, 59 | SCHEDULER__START, SCHEDULER__MAX}, 60 | 61 | {VF_NUMBER__KEY, VF_NUMBER__DEFAULT, 62 | VF_NUMBER__START, VF_NUMBER__MAX}, 63 | 64 | {PF_FB__KEY, PF_FB__DEFAULT, 65 | PF_FB__START, PF_FB__MAX}, 66 | 67 | {VF_FB__KEY, VF_FB__DEFAULT, 68 | VF_FB__START, VF_FB__MAX}, 69 | 70 | {SCHED_INTERVAL__KEY, SCHED_INTERVAL__DEFAULT, 71 | SCHED_INTERVAL__START, SCHED_INTERVAL__MAX}, 72 | 73 | {SCHED_INTERVAL_US__KEY, SCHED_INTERVAL_US__DEFAULT, 74 | SCHED_INTERVAL_US__START, SCHED_INTERVAL_US__MAX}, 75 | 76 | {FB_CLEAR__KEY, FB_CLEAR__DEFAULT, FB_CLEAR__START, FB_CLEAR__MAX}, 77 | }; 78 | 79 | #define MAX_OPTION (sizeof(config_options)/sizeof(struct config_option)) 80 | #define MAX_CONFIG_FILE_LENGTH 1024 81 | 82 | /* Options input from command line */ 83 | #define COMMAND_LINE_OPTION_DEFAULT -1 84 | static uint32_t fb_option = COMMAND_LINE_OPTION_DEFAULT; 85 | module_param(fb_option, uint, S_IRUGO); 86 | MODULE_PARM_DESC(fb_option, "Frame Buffer Partition.0:static partition; 1: dynamic partition"); 87 | 88 | static uint32_t sched_option = COMMAND_LINE_OPTION_DEFAULT; 89 | module_param(sched_option, uint, S_IRUGO); 90 | MODULE_PARM_DESC(sched_option, "GPU scheduler. 0: round robin solid; 1: predictable perf; 2: round robin liquid"); 91 | 92 | static unsigned int vf_num = COMMAND_LINE_OPTION_DEFAULT; 93 | module_param(vf_num, uint, S_IRUGO); 94 | MODULE_PARM_DESC(vf_num, "number of enabled virtual functions. 0: default number of VF in pci sriov config space; N: enable N VFs"); 95 | 96 | static unsigned int pf_fb = COMMAND_LINE_OPTION_DEFAULT; 97 | module_param(pf_fb, uint, S_IRUGO); 98 | MODULE_PARM_DESC(pf_fb, "Frame Buffer Size in MegaBytes for PF"); 99 | 100 | static unsigned int vf_fb = COMMAND_LINE_OPTION_DEFAULT; 101 | module_param(vf_fb, uint, S_IRUGO); 102 | MODULE_PARM_DESC(vf_fb, "Frame Buffer Size in MegaBytes for VF"); 103 | 104 | 105 | static unsigned int sched_interval = COMMAND_LINE_OPTION_DEFAULT; 106 | module_param(sched_interval, uint, S_IRUGO); 107 | MODULE_PARM_DESC(sched_interval, "Scheduling time quanta in milliseconds. 0: default quanta(6ms)"); 108 | 109 | static unsigned int sched_interval_us = COMMAND_LINE_OPTION_DEFAULT; 110 | module_param(sched_interval_us, uint, S_IRUGO); 111 | MODULE_PARM_DESC(sched_interval_us, "Scheduling time quanta in microseconds " 112 | "Delta scheduling time add on sched_interval " 113 | "0: default quanta(0us) range from 0-999"); 114 | 115 | static unsigned int fb_clear = COMMAND_LINE_OPTION_DEFAULT; 116 | module_param(fb_clear, uint, S_IRUGO); 117 | MODULE_PARM_DESC(fb_clear, "Clear the VRAM for VF. 0:Skipping; 1: clear FB of VF when VF is free or down"); 118 | 119 | static int search_config_key(char *key) 120 | { 121 | int index; 122 | int ret = -1; 123 | 124 | for (index = 0 ; index < MAX_OPTION; ++index) { 125 | if (!strcmp(config_options[index].name, key)) { 126 | ret = index; 127 | break; 128 | } 129 | } 130 | return ret; 131 | } 132 | 133 | static int validate_option(int index, int value) 134 | { 135 | int ret = -1; 136 | 137 | if (index >= CONFIG_OPTION__START && index < CONFIG_OPTION__MAX) { 138 | if (value >= config_options[index].min 139 | && value <= config_options[index].max) 140 | ret = 0; 141 | } 142 | 143 | return ret; 144 | } 145 | 146 | static int get_config_option(int index) 147 | { 148 | if (index >= CONFIG_OPTION__START 149 | && index < CONFIG_OPTION__MAX) 150 | return config_options[index].value; 151 | 152 | return -1; 153 | } 154 | 155 | static void set_config_option(int index, int value) 156 | { 157 | if (index >= CONFIG_OPTION__START 158 | && index < CONFIG_OPTION__MAX) 159 | config_options[index].value = value; 160 | } 161 | 162 | static int parse_config_file(char *data, unsigned long long size) 163 | { 164 | const char delimiters[] = " =\n\t"; 165 | char *token; 166 | char *running; 167 | int empty; 168 | int index; 169 | 170 | running = data; 171 | do { 172 | /* Get the key. */ 173 | /* Get an non-empty token(including NULL token). */ 174 | do { 175 | empty = 0; 176 | token = strsep(&running, delimiters); 177 | if (token) 178 | empty = (strlen(token) == 0); 179 | } while (empty); 180 | 181 | 182 | /* expecting a key. */ 183 | if (token != NULL) { 184 | index = search_config_key(token); 185 | if (index < 0) { 186 | /* unknown token found, Error in the 187 | * config file, exit. 188 | */ 189 | gim_err("AMD GIM unknown token: %s\n", token); 190 | break; 191 | } 192 | 193 | /* Get the value. */ 194 | /* Get an non-empty token(including NULL token). */ 195 | do { 196 | empty = 0; 197 | token = strsep(&running, delimiters); 198 | 199 | if (token) 200 | empty = (strlen(token) == 0); 201 | } while (empty); 202 | 203 | /* expecting a value. */ 204 | if (token != NULL) { 205 | int value; 206 | int ret; 207 | 208 | ret = kstrtoint(token, 10, &value); 209 | if (ret) { 210 | gim_err("Failed to transfer str: %s\n", 211 | token); 212 | } 213 | 214 | if (validate_option(index, value) == 0) 215 | config_options[index].value = value; 216 | 217 | gim_info("AMD GIM %s = %d\n", 218 | config_options[index].name, 219 | config_options[index].value); 220 | } 221 | } 222 | } while (token != NULL); 223 | 224 | return 0; 225 | } 226 | 227 | static int read_config_file(void) 228 | { 229 | int ret; 230 | unsigned long long size; 231 | struct file *config; 232 | char *content; 233 | int rc; 234 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) 235 | loff_t loff_t = 0; 236 | #endif 237 | 238 | config = filp_open(GIM_CONFIG_PATH, O_RDONLY, 0); 239 | if (IS_ERR(config)) { 240 | rc = PTR_ERR(config); 241 | gim_warn("can't open %s because of error: %d\n", 242 | GIM_CONFIG_PATH, rc); 243 | return -1; 244 | } 245 | 246 | size = i_size_read(file_inode(config)) + 1; 247 | content = kzalloc(size, GFP_KERNEL); 248 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) 249 | ret = kernel_read(config, 0, content, size); 250 | #else 251 | ret = kernel_read(config, content, size, &loff_t); 252 | #endif 253 | parse_config_file(content, size); 254 | kfree(content); 255 | filp_close(config, NULL); 256 | return 0; 257 | } 258 | 259 | static int write_config_file(char *content) 260 | { 261 | int ret = 0; 262 | struct file *config; 263 | int rc; 264 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) 265 | loff_t loff_t = 0; 266 | #endif 267 | config = filp_open(GIM_CONFIG_PATH, O_CREAT|O_RDWR, 0); 268 | if (IS_ERR(config)) { 269 | rc = PTR_ERR(config); 270 | gim_warn("can't open %s because of error: %d\n", 271 | GIM_CONFIG_PATH, rc); 272 | return -1; 273 | } 274 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) 275 | ret = kernel_write(config, content, strlen(content), 0); 276 | #else 277 | ret = kernel_write(config, content, strlen(content), &loff_t); 278 | #endif 279 | vfs_fsync(config, 0); 280 | filp_close(config, NULL); 281 | 282 | return 0; 283 | } 284 | 285 | int save_config(void) 286 | { 287 | char *buf; 288 | int index; 289 | int cursor = 0; 290 | 291 | buf = vmalloc(MAX_CONFIG_FILE_LENGTH); 292 | memset(buf, 0, MAX_CONFIG_FILE_LENGTH); 293 | for (index = 0; index < MAX_OPTION; ++index) { 294 | cursor += snprintf(buf + cursor, 295 | MAX_CONFIG_FILE_LENGTH - cursor, 296 | "%s=%d\n", 297 | config_options[index].name, 298 | config_options[index].value); 299 | 300 | if (cursor >= MAX_CONFIG_FILE_LENGTH) 301 | break; 302 | } 303 | 304 | write_config_file(buf); 305 | vfree(buf); 306 | return 0; 307 | } 308 | 309 | int init_config(void) 310 | { 311 | read_config_file(); 312 | 313 | /* options of command line override options in config file. */ 314 | if (validate_option(CONFIG_OPTION__FB, fb_option) == 0) 315 | set_config_option(CONFIG_OPTION__FB, fb_option); 316 | 317 | if (validate_option(CONFIG_OPTION__SCHEDULER, sched_option) == 0) 318 | set_config_option(CONFIG_OPTION__SCHEDULER, sched_option); 319 | 320 | if (validate_option(CONFIG_OPTION__VF_NUMBER, vf_num) == 0) 321 | set_config_option(CONFIG_OPTION__VF_NUMBER, vf_num); 322 | 323 | if (validate_option(CONFIG_OPTION__PF_FB_SIZE, pf_fb) == 0) 324 | set_config_option(CONFIG_OPTION__PF_FB_SIZE, pf_fb); 325 | 326 | if (validate_option(CONFIG_OPTION__VF_FB_SIZE, vf_fb) == 0) 327 | set_config_option(CONFIG_OPTION__VF_FB_SIZE, vf_fb); 328 | 329 | if (validate_option(CONFIG_OPTION__SCHED_INTERVAL, 330 | sched_interval) == 0) 331 | set_config_option(CONFIG_OPTION__SCHED_INTERVAL, 332 | sched_interval); 333 | if (validate_option(CONFIG_OPTION__SCHED_INTERVAL_US, 334 | sched_interval_us) == 0) 335 | set_config_option(CONFIG_OPTION__SCHED_INTERVAL_US, 336 | sched_interval_us); 337 | 338 | if (validate_option(CONFIG_OPTION__FB_CLEAR, fb_clear) == 0) 339 | set_config_option(CONFIG_OPTION__FB_CLEAR, fb_clear); 340 | 341 | gim_info("INIT CONFIG\n"); 342 | 343 | /* save options to config file. */ 344 | save_config(); 345 | 346 | return 0; 347 | } 348 | 349 | uint32_t get_fb_partition_option(void) 350 | { 351 | return get_config_option(CONFIG_OPTION__FB); 352 | } 353 | 354 | uint32_t get_scheduler_option(void) 355 | { 356 | return get_config_option(CONFIG_OPTION__SCHEDULER); 357 | } 358 | 359 | uint32_t get_vf_number_option(void) 360 | { 361 | return get_config_option(CONFIG_OPTION__VF_NUMBER); 362 | } 363 | 364 | uint32_t get_pf_fb_option(void) 365 | { 366 | return get_config_option(CONFIG_OPTION__PF_FB_SIZE); 367 | } 368 | 369 | uint32_t get_vf_fb_option(void) 370 | { 371 | return get_config_option(CONFIG_OPTION__VF_FB_SIZE); 372 | } 373 | 374 | uint32_t get_sched_interval_option(void) 375 | { 376 | return get_config_option(CONFIG_OPTION__SCHED_INTERVAL); 377 | } 378 | 379 | uint32_t get_sched_interval_us_option(void) 380 | { 381 | return get_config_option(CONFIG_OPTION__SCHED_INTERVAL_US); 382 | } 383 | 384 | uint32_t get_fb_clear_option(void) 385 | { 386 | return get_config_option(CONFIG_OPTION__FB_CLEAR); 387 | } 388 | 389 | uint32_t set_option(int index, int value) 390 | { 391 | uint32_t res = -1; 392 | 393 | if (validate_option(index, value) == 0) { 394 | set_config_option(index, value); 395 | save_config(); 396 | res = 0; 397 | } 398 | return res; 399 | } 400 | 401 | -------------------------------------------------------------------------------- /drv/gim_unwrapper.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2017 Advanced Micro Devices, Inc. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | #include "gim_interface.h" 27 | #include "gim_command.h" 28 | #include "gim_unwrapper.h" 29 | #include "gim_flr.h" 30 | #include "gim_debug.h" 31 | 32 | static char output_buf[SYS_BUFFER_SIZE]; 33 | 34 | uint32_t call_interface_functions(const void *buf, size_t count) 35 | { 36 | struct command *command = (struct command *)buf; 37 | struct output *output = (struct output *)output_buf; 38 | 39 | output->size = sizeof(struct output); 40 | output->result = GIM_ERROR; 41 | 42 | if (count >= sizeof(struct command)) { 43 | if (command->version != GIM_HEADER_VER) { 44 | output->result = GIM_INVALIDATE_COMMAND_SIZE; 45 | return GIM_INVALIDATE_VERSION; 46 | } 47 | 48 | } 49 | 50 | switch (command->command) { 51 | case GIM__MA__GET_OPTION: { 52 | struct get_option_input *in = 53 | (struct get_option_input *)command; 54 | struct get_option_output *out = 55 | (struct get_option_output *)output_buf; 56 | 57 | if (in->size != sizeof(struct get_option_input)) { 58 | out->result = GIM_INVALIDATE_INPUT_SIZE; 59 | return GIM_INVALIDATE_INPUT_SIZE; 60 | } 61 | out->size = sizeof(struct get_option_output); 62 | out->value = get_opt(in->index); 63 | out->result = (out->value >= 0) ? 64 | GIM_OK : GIM_INVALIDATE_OPTION; 65 | break; 66 | } 67 | 68 | case GIM__MA__SET_OPTION: { 69 | struct set_option_input *in = 70 | (struct set_option_input *)command; 71 | 72 | if (in->size != sizeof(struct set_option_input)) { 73 | output->result = GIM_INVALIDATE_INPUT_SIZE; 74 | return GIM_INVALIDATE_INPUT_SIZE; 75 | } 76 | output->result = (set_opt(in->index, in->value) == 0) 77 | ? GIM_OK : GIM_INVALIDATE_OPTION; 78 | break; 79 | } 80 | 81 | case GIM__MA__GET_PF_COUNT: { 82 | struct get_pf_count_output *out = 83 | (struct get_pf_count_output *)output_buf; 84 | 85 | if (command->size != sizeof(struct command)) { 86 | out->result = GIM_INVALIDATE_COMMAND_SIZE; 87 | return GIM_INVALIDATE_COMMAND_SIZE; 88 | } 89 | 90 | out->size = sizeof(struct get_pf_count_output); 91 | out->result = GIM_OK; 92 | out->pf_count = get_pf_count(); 93 | break; 94 | } 95 | 96 | case GIM__MA__ENUMERATE_PFS: { 97 | struct enumerate_pfs_output *out = 98 | (struct enumerate_pfs_output *)output_buf; 99 | 100 | if (command->size != sizeof(struct command)) { 101 | out->result = GIM_INVALIDATE_COMMAND_SIZE; 102 | return GIM_INVALIDATE_COMMAND_SIZE; 103 | } 104 | 105 | out->pf_count = enumerate_pfs((SYS_BUFFER_SIZE - output->size) / 106 | sizeof(uint32_t), out->pf_bdfs); 107 | out->result = GIM_OK; 108 | if (out->pf_count > 0) 109 | out->size = sizeof(struct enumerate_pfs_output) + 110 | (out->pf_count - 1) * sizeof(uint32_t); 111 | else 112 | out->size = 113 | sizeof(struct enumerate_pfs_output) - sizeof(uint32_t); 114 | break; 115 | } 116 | 117 | case GIM__SRIOV__GET_TOTAL_VF_COUNT: { 118 | struct get_total_vfs_input *in = 119 | (struct get_total_vfs_input *)command; 120 | struct get_total_vfs_output *out = ( 121 | struct get_total_vfs_output *)output_buf; 122 | 123 | if (in->size != sizeof(struct get_total_vfs_input)) { 124 | out->result = GIM_INVALIDATE_INPUT_SIZE; 125 | return GIM_INVALIDATE_INPUT_SIZE; 126 | } 127 | out->vf_count = get_total_vfs(in->pf_bdf); 128 | out->result = GIM_OK; 129 | out->size = sizeof(struct get_total_vfs_output); 130 | break; 131 | } 132 | 133 | case GIM__SRIOV__ENABLE: { 134 | struct enable_sriov_input *in = 135 | (struct enable_sriov_input *)command; 136 | struct output *out = (struct output *)output_buf; 137 | 138 | if (in->size != sizeof(struct enable_sriov_input)) { 139 | out->result = GIM_INVALIDATE_INPUT_SIZE; 140 | return GIM_INVALIDATE_INPUT_SIZE; 141 | } 142 | 143 | out->result = enable_sriov(in->pf_bdf, in->vfs_count); 144 | out->size = sizeof(struct output); 145 | break; 146 | } 147 | 148 | case GIM__SRIOV__DISABLE: { 149 | struct disable_sriov_input *in = 150 | (struct disable_sriov_input *)command; 151 | struct output *out = (struct output *)output_buf; 152 | 153 | if (in->size != sizeof(struct disable_sriov_input)) { 154 | out->result = GIM_INVALIDATE_INPUT_SIZE; 155 | return GIM_INVALIDATE_INPUT_SIZE; 156 | } 157 | 158 | out->result = disable_sriov(in->pf_bdf); 159 | out->size = sizeof(struct output); 160 | break; 161 | } 162 | 163 | case GIM__VF__GET_AVAILABLE_VF_COUNT: { 164 | struct get_available_vf_count_input *in = 165 | (struct get_available_vf_count_input *)command; 166 | struct get_available_vf_count_output *out = 167 | (struct get_available_vf_count_output *)output_buf; 168 | 169 | if (in->size != sizeof(struct get_available_vf_count_input)) { 170 | out->result = GIM_INVALIDATE_INPUT_SIZE; 171 | return GIM_INVALIDATE_INPUT_SIZE; 172 | } 173 | out->vf_count = get_available_vf_count(in->pf_bdf); 174 | out->result = GIM_OK; 175 | out->size = sizeof(struct get_available_vf_count_output); 176 | break; 177 | } 178 | 179 | case GIM__VF__ENUMERATE_AVAILABLE_VFS: { 180 | struct enumerate_available_vfs_input *in = 181 | (struct enumerate_available_vfs_input *)command; 182 | struct enumerate_available_vfs_output *out = 183 | (struct enumerate_available_vfs_output *)output_buf; 184 | 185 | if (in->size != sizeof(struct enumerate_available_vfs_input)) { 186 | output->result = GIM_INVALIDATE_INPUT_SIZE; 187 | return GIM_INVALIDATE_INPUT_SIZE; 188 | } 189 | 190 | out->vf_count = enumerate_available_vfs(in->pf_bdf, 191 | (SYS_BUFFER_SIZE - output->size) / sizeof(uint32_t), 192 | out->vf_bdfs); 193 | out->result = GIM_OK; 194 | if (out->vf_count > 0) 195 | out->size = 196 | sizeof(struct enumerate_available_vfs_output) 197 | + (out->vf_count - 1) * sizeof(uint32_t); 198 | else 199 | out->size = 200 | sizeof(struct enumerate_available_vfs_output) 201 | - sizeof(uint32_t); 202 | 203 | break; 204 | } 205 | 206 | case GIM__VF__ENUMERATE_VFS: { 207 | struct enumerate_vfs_input *in = 208 | (struct enumerate_vfs_input *)command; 209 | struct enumerate_vfs_output *out = 210 | (struct enumerate_vfs_output *)output_buf; 211 | 212 | if (in->size != sizeof(struct enumerate_vfs_input)) { 213 | output->result = GIM_INVALIDATE_INPUT_SIZE; 214 | return GIM_INVALIDATE_INPUT_SIZE; 215 | } 216 | out->vf_count = enumerate_all_vfs(in->pf_bdf, 217 | (SYS_BUFFER_SIZE - output->size) / 218 | sizeof(struct vf_info), out->vf_info); 219 | out->result = GIM_OK; 220 | if (out->vf_count > 0) 221 | out->size = sizeof(struct enumerate_vfs_output) + 222 | (out->vf_count - 1) * sizeof(struct vf_info); 223 | else 224 | out->size = sizeof(struct enumerate_vfs_output) - 225 | sizeof(struct vf_info); 226 | break; 227 | } 228 | 229 | /* used by QEMU */ 230 | case GIM__VF__ALLOC: { 231 | struct vf_alloc_input *in = (struct vf_alloc_input *)command; 232 | struct vf_alloc_output *out = 233 | (struct vf_alloc_output *)output_buf; 234 | 235 | if (in->size != sizeof(struct vf_alloc_input)) { 236 | output->result = GIM_INVALIDATE_INPUT_SIZE; 237 | return GIM_INVALIDATE_INPUT_SIZE; 238 | } 239 | 240 | out->vf_bdf = alloc_vf(in->pf_bdf, in->domid, 241 | in->pid, in->fb_size, in->sched_level); 242 | if (out->vf_bdf) 243 | out->result = GIM_OK; 244 | else 245 | out->result = GIM_ERROR; /* no available VF */ 246 | break; 247 | } 248 | 249 | case GIM__VF__ALLOC_WITH_VBDF: { 250 | struct vf_alloc_with_vbdf_input *in = 251 | (struct vf_alloc_with_vbdf_input *)command; 252 | struct vf_alloc_with_vbdf_output *out = 253 | (struct vf_alloc_with_vbdf_output *)output_buf; 254 | 255 | if (in->size != sizeof(struct vf_alloc_with_vbdf_input)) { 256 | output->result = GIM_INVALIDATE_INPUT_SIZE; 257 | return GIM_INVALIDATE_INPUT_SIZE; 258 | } 259 | 260 | alloc_vf_from_bdf(in->vf_bdf, in->domid, 261 | in->pid, in->fb_size, in->sched_level); 262 | out->result = GIM_OK; 263 | break; 264 | } 265 | 266 | case GIM__VF__SET_MMR_INFO: { 267 | struct vf_mmr_info *in = (struct vf_mmr_info *)command; 268 | 269 | if (in->size != sizeof(struct vf_mmr_info)) { 270 | output->result = GIM_INVALIDATE_INPUT_SIZE; 271 | return GIM_INVALIDATE_INPUT_SIZE; 272 | } 273 | map_mmr(in->vf_bdf, in->physcal_add, in->mmr_size); 274 | break; 275 | } 276 | 277 | case GIM__VF__FREE: { 278 | struct vf_free_input *in = (struct vf_free_input *)command; 279 | 280 | if (in->size != sizeof(struct vf_free_input)) { 281 | output->result = GIM_INVALIDATE_INPUT_SIZE; 282 | return GIM_INVALIDATE_INPUT_SIZE; 283 | } 284 | 285 | free_vf_from_bdf(in->vf_bdf); 286 | break; 287 | } 288 | 289 | case GIM__DOMAIN__SHUTDOWN: { 290 | struct domain_shutdown_input *in = 291 | (struct domain_shutdown_input *)command; 292 | 293 | if (in->size != sizeof(struct domain_shutdown_input)) { 294 | output->result = GIM_INVALIDATE_INPUT_SIZE; 295 | return GIM_INVALIDATE_INPUT_SIZE; 296 | } 297 | 298 | free_vf_from_domid(in->domid); 299 | break; 300 | } 301 | 302 | case GIM__VF__SET_PID: 303 | break; 304 | 305 | case GIM__VF__SET_FRAME_BUFFER: 306 | break; 307 | 308 | case GIM__VF__SET_SCHEDULE_LEVEL: 309 | break; 310 | 311 | case GIM__VF__SET_ACPI_EVENT: 312 | break; 313 | 314 | case GIM__FB__GET_MAX_SLOT: { 315 | struct get_max_fb_slot_input *in = 316 | (struct get_max_fb_slot_input *)command; 317 | struct get_max_fb_slot_output *out = 318 | (struct get_max_fb_slot_output *)output_buf; 319 | 320 | if (in->size != sizeof(struct get_max_fb_slot_input)) { 321 | output->result = GIM_INVALIDATE_INPUT_SIZE; 322 | return GIM_INVALIDATE_INPUT_SIZE; 323 | } 324 | 325 | out->max_fb_slot_size = get_max_fb_slot(in->pf_bdf); 326 | out->result = GIM_OK; 327 | break; 328 | } 329 | 330 | case GIM__FB__ALLOC: 331 | break; 332 | 333 | case GIM__FB__FREE: 334 | break; 335 | 336 | case GIM__SCHEDULER__PAUSE: { 337 | struct pause_scheduler_input *in = 338 | (struct pause_scheduler_input *)command; 339 | 340 | pause_sched(in->pf_bdf); 341 | break; 342 | } 343 | 344 | case GIM__SCHEDULER__RESUME: { 345 | struct resume_scheduler_input *in = 346 | (struct resume_scheduler_input *)command; 347 | 348 | start_scheduler(in->pf_bdf); 349 | break; 350 | } 351 | 352 | case GIM__SCHEDULER__GET_ACTIVE_FUNCTIONS: 353 | break; 354 | 355 | case GIM__SCHEDULER__INIT: 356 | break; 357 | 358 | case GIM__SCHEDULER__IDLE: 359 | break; 360 | 361 | case GIM__SCHEDULER__SAVE: 362 | break; 363 | 364 | case GIM__SCHEDULER__LOAD: 365 | break; 366 | 367 | case GIM__SCHEDULER__RUN: 368 | break; 369 | 370 | case GIM__SCHEDULER__CONTEXT_SWITCH: { 371 | struct context_switch_input *in = 372 | (struct context_switch_input *)command; 373 | 374 | do_world_switch(in->pf_bdf); 375 | break; 376 | } 377 | 378 | case GIM__SCHEDULER__GET_CUR_VF: 379 | gim_info("GIM__SCHEDULER__GET_CUR_VF - not yet supported\n"); 380 | break; 381 | 382 | case GIM__DEBUG__MANUAL_SWITCH: { 383 | struct manual_switch_input *in = 384 | (struct manual_switch_input *)command; 385 | 386 | trgger_single_switch(in->pf_bdf); 387 | break; 388 | } 389 | 390 | case GIM__DEBUG__ENABLE_PREEMPTION: { 391 | struct enable_preemption_input *in = 392 | (struct enable_preemption_input *)command; 393 | 394 | enable_preemption(in->pf_bdf, in->enable); 395 | break; 396 | } 397 | 398 | case GIM__DEBUG__SEND_SIGNAL: { 399 | struct send_signal_input *in = 400 | (struct send_signal_input *)command; 401 | 402 | send_signal(in->vm_id, in->signal_id); 403 | break; 404 | } 405 | 406 | case GIM__RESET__VF_FLR: { 407 | uint32_t bdf = command->data[0]; 408 | 409 | gim_info("GIM__RESET__VF_FLR for BDF 0x%04x - not yet supported\n", 410 | bdf); 411 | break; 412 | } 413 | 414 | case GIM__RESET__PF_FLR: 415 | /* uint32_t bdf = command->data[0]; */ 416 | gim_info("GIM__RESET__PF_FLR - not yet supported\n"); 417 | break; 418 | 419 | case GIM__RESET__PF_FLR_SOFT: 420 | /* uint32_t bdf = command->data[0]; */ 421 | gim_info("GIM__RESET__PF_FLR_SOFT - not yet supported\n"); 422 | break; 423 | 424 | case GIM__RESET__ENABLE_BUS_MASTER: 425 | gim_info("GIM__RESET__ENABLE_BUS_MASTER - not yet supported\n"); 426 | break; 427 | 428 | case GIM__RESET__DISABLE_BUS_MASTER: 429 | gim_info("GIM__RESET__DISABLE_BUS_MASTER - not yet supported\n"); 430 | break; 431 | 432 | case GIM__RESET__IS_ASIC_HUNG: 433 | gim_info("GIM__RESET__IS_ASIC_HUNG - not yet supported\n"); 434 | break; 435 | 436 | case GIM__RESET__NOTIFY_RESET: { 437 | uint32_t bdf = command->data[0]; 438 | 439 | gim_info("GIM__RESET__NOTIFY_RESET for BDF 0x%04x - not yet supported\n", 440 | bdf); 441 | break; 442 | } 443 | 444 | } 445 | return true; 446 | } 447 | 448 | 449 | uint32_t respond_interface_functions(char *buf) 450 | { 451 | struct output *output = (struct output *)output_buf; 452 | 453 | memcpy(buf, output, 454 | ((output->size < SYS_BUFFER_SIZE) ? output->size : SYS_BUFFER_SIZE)); 455 | return output->size; 456 | } 457 | 458 | --------------------------------------------------------------------------------