리눅스 커널 기여(Contribution) - 패치 작성 및 패치 반영(Upstream) 확인하기
이전 시간에는 리눅스 커널 기여(Contribution) 하기 전에 준비해야 할 사항을 소개했습니다.
- gmail 계정 생성
- mutt 설치 및 설정
이번 시간에는 커널 패치를 작성해보고 패치를 리눅스 매인테이너(Maintainer)에게 보내는 과정을 소개합니다.
그리고 업스트림(Upstream)된 패치를 확인하는 방법도 말씀드리겠습니다.
<< 오류 코드 확인하기 >>
먼저 패치를 작성하기 전 커널 코드를 볼까요?
참고로 다음 함수는 AMD/PowerPlay 드라이버입니다.
[drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c]
01 static int smu8_start_smu(struct pp_hwmgr *hwmgr)
02 {
03 struct amdgpu_device *adev = hwmgr->adev;
04
05 uint32_t index = SMN_MP1_SRAM_START_ADDR +
06 SMU8_FIRMWARE_HEADER_LOCATION +
07 offsetof(struct SMU8_Firmware_Header, Version);
08
09 if (hwmgr == NULL || hwmgr->device == NULL)
10 return -EINVAL;
11
12 cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
13 hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
14 pr_info("smu version %02d.%02d.%02d\n",먼저 03번째 줄 코드를 보겠습니다.
03 struct amdgpu_device *adev = hwmgr->adev;
위 코드 왼쪽 부분을 눈으로 따라가 봅시다.
struct pp_hwmgr 타입인 hwmgr 포인터의 adev 필드를 struct amdgpu_device 구조체 타입인 adev에 저장합니다.
뭐가, 문제란 소리지?
조금만 더 읽어주세요. 다음 09~10번째 줄 코드를 분석하겠습니다.
09 if (hwmgr == NULL || hwmgr->device == NULL) 10 return -EINVAL;
smu8_start_smu() 함수 인자로 전달된 'hwmgr' 포인터나 'hwmgr->device' 포인터가 NULL이면
-EINVAL를 반환합니다.
여기까지 코드를 분석하고 나면 '뭐가 문제지?'란 생각이 들 수 있습니다. 하지만 논리적인 오류가 있습니다.
09~10번째 줄 코드와 같이 'hwmgr' 포인터나 'hwmgr->device' 포인터가 NULL을 체크한 다음에
다음 코드를 실행했어야 합니다.
03 struct amdgpu_device *adev = hwmgr->adev;
'hwmgr' 포인터가 NULL이면 03번째 줄에서 NULL Pointer Dereference(NULL 포인터 역참조)로 커널 패닉이 먼저 발생합니다.
<< 패치 코드 작성하기 >>
오류 코드를 확인한 다음에 패치 코드를 작성했습니다.
[drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c]
01 static int smu8_start_smu(struct pp_hwmgr *hwmgr)
02 {
03 struct amdgpu_device *adev;
04
05 uint32_t index = SMN_MP1_SRAM_START_ADDR +
06 SMU8_FIRMWARE_HEADER_LOCATION +
07 offsetof(struct SMU8_Firmware_Header, Version);
08
09 if (hwmgr == NULL || hwmgr->device == NULL)
10 return -EINVAL;
11
12 adev = hwmgr->adev;
13
14 cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
15 hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
16 pr_info("smu version %02d.%02d.%02d\n",09~10번째 줄 코드와 같이 'hwmgr' 포인터나 'hwmgr->device' 포인터가 NULL을 먼저 체크한 다음에
다음 12번째 줄 코드를 실행합니다.
12 adev = hwmgr->adev;
이제 패치 코드 포멧으로 확인해보겠습니다.
austindh.kim~/src/linux_kernel_source/linux-next$ git diff
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
index 8189fe4..4728aa2 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
@@ -722,16 +722,17 @@ static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr)
static int smu8_start_smu(struct pp_hwmgr *hwmgr)
{
- struct amdgpu_device *adev = hwmgr->adev;
+ struct amdgpu_device *adev;
uint32_t index = SMN_MP1_SRAM_START_ADDR +
SMU8_FIRMWARE_HEADER_LOCATION +
offsetof(struct SMU8_Firmware_Header, Version);
-
if (hwmgr == NULL || hwmgr->device == NULL)
return -EINVAL;
+ adev = hwmgr->adev;
+
cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
pr_info("smu version %02d.%02d.%02d\n", << 패치 커밋 생성하기 >>
이제는 리눅스 커널 메인테이너에게 보낼 커밋 패치를 작성해보겠습니다.
먼저 'git status' 명령어를 입력해볼까요?
austindh.kim~/src/linux_kernel_source/linux-next$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c이번에는 커밋을 하나 생성합니다.
austindh.kim~/src/linux_kernel_source/linux-next$ git add drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c austindh.kim~/src/linux_kernel_source/linux-next$ git commit -m "drm/amdgpu: Move null pointer dereference check"
커밋에 대한 설명이 필요하니 'git commit --amend' 명령어를 입력해 패치 내용을 추가합니다.
austindh.kim~/src/linux_kernel_source/linux-next$ git commit --amend 1 drm/amdgpu: Move null pointer dereference check 2 3 Null pointer dereference check should have been checked, 4 ahead of below routine. 5 struct amdgpu_device *adev = hwmgr->adev; 6 7 With this commit, it could avoid potential NULL dereference. 8 # Please enter the commit message for your changes. Lines starting 9 # with '#' will be ignored, and an empty message aborts the commit. 10 # 11 # Date: Thu Aug 30 17:07:04 2019 +0900 12 # 13 # On branch master 14 # Your branch is ahead of 'origin/master' by 1 commit. 15 # (use "git push" to publish your local commits) 16 # 17 # Changes to be committed: 18 # modified: drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c 19 #
다음 3~7번째 줄 메시지를 추가했습니다. 패치가 무엇인지 정확히 기입했습니다.
1 drm/amdgpu: Move null pointer dereference check 2 3 Null pointer dereference check should have been checked, 4 ahead of below routine. 5 struct amdgpu_device *adev = hwmgr->adev; 6 7 With this commit, it could avoid potential NULL dereference.
이번에는 'git log -p' 명령어를 입력해 소스 내역과 커밋을 함께 확인합시다.
austindh.kim~/src/linux_kernel_source/linux-next$ git log -p
commit 27b1f563c69f6a4af66ea8ccd8a1643c072b8299
Author: Austin Kim <austindh.kim@gmail.com>
Date: Thu Aug 29 17:08:38 2019 +0900
drm/amdgpu: Move null pointer dereference check
Null pointer dereference check should have been checked,
ahead of below routine.
struct amdgpu_device *adev = hwmgr->adev;
With this commit, it could avoid potential NULL dereference.
Signed-off-by: Austin Kim <austindh.kim@gmail.com>
---
drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
index 8189fe4..4728aa2 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
@@ -722,16 +722,17 @@ static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr)
static int smu8_start_smu(struct pp_hwmgr *hwmgr)
{
- struct amdgpu_device *adev = hwmgr->adev;
+ struct amdgpu_device *adev;
uint32_t index = SMN_MP1_SRAM_START_ADDR +
SMU8_FIRMWARE_HEADER_LOCATION +
offsetof(struct SMU8_Firmware_Header, Version);
-
if (hwmgr == NULL || hwmgr->device == NULL)
return -EINVAL;
+ adev = hwmgr->adev;
+
cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
pr_info("smu version %02d.%02d.%02d\n",이번에는 'git format-patch -1' 명령어를 입력해 패치 파일을 하나 생성합니다.
austindh.kim~/src/linux_kernel_source/linux-next$ git format-patch -1 0001-drm_amdgpu_Move_null_pointer_dereference_check.patch
ls '파일명' 포멧으로 명령어를 입력하니 '0001-drm_amdgpu_Move_null_pointer_dereference_check.patch' 파일이 생성됐음을 확인할 수 있습니다.
austindh.kim~/src/linux_kernel_source/linux-next$ ls 0001-drm_amdgpu_Move_null_pointer_dereference_check.patch
이번에는 './scripts/checkpatch.pl' 스크립트를 실행해 패치 코드의 포멧을 확인합니다.
austindh.kim~/src/linux_kernel_source/linux-next$ ./scripts/checkpatch.pl 0001-drm_amdgpu_Move_null_pointer_dereference_check.patch
0001-drm_amdgpu_Move_null_pointer_dereference_check.patch has no style problems, please review.
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.이제 mutt 프로그램을 사용해 작성한 패치 세트를 커널 메인테이너에게 송부합니다.
austindh.kim~/src/linux_kernel_source/linux-next$ mutt -H 0001-drm_amdgpu_Move_null_pointer_dereference_check.patch
<< 패치 확인하기 >>
아래 커널 메일링 리스트 아카이브 사이트에 가보면,
https://lkml.org/lkml/2019/8/30/644
제가 올린 패치를 확인할 수 있는데 drm/amdgpu subsystem maintainer께서 다음과 같은 커맨드를 하셨음을 알 수 있습니다.
Applied. thanks! Alex
커맨트 내용은 다음과 같습니다.
From Alex Deucher <>
Date Fri, 30 Aug 2019 11:09:43 -0400
Subject Re: [PATCH] drm/amdgpu: Move null pointer dereference check
share
On Fri, Aug 30, 2019 at 8:43 AM Austin Kim <austindh.kim@gmail.com> wrote:
>
> Null pointer dereference check should have been checked,
> ahead of below routine.
> struct amdgpu_device *adev = hwmgr->adev;
>
> With this commit, it could avoid potential NULL dereference.
>
> Signed-off-by: Austin Kim <austindh.kim@gmail.com>
Applied. thanks!
Alex
> ---
> drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
> index 8189fe4..4728aa2 100644
> --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
> +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
> @@ -722,16 +722,17 @@ static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr)
>
> static int smu8_start_smu(struct pp_hwmgr *hwmgr)
> {
> - struct amdgpu_device *adev = hwmgr->adev;
> + struct amdgpu_device *adev;
>
> uint32_t index = SMN_MP1_SRAM_START_ADDR +
> SMU8_FIRMWARE_HEADER_LOCATION +
> offsetof(struct SMU8_Firmware_Header, Version);
>
> -
> if (hwmgr == NULL || hwmgr->device == NULL)
> return -EINVAL;
>
> + adev = hwmgr->adev;
> +
> cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
> hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
> pr_info("smu version %02d.%02d.%02d\n",
> --
> 2.6.2
>3일 후에 아래 사이트에서 가보니,
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/
제가 작성한 패치가 리눅스 커널 메인 소스 코드에 반영(Upstream)된 것을 확인할 수 있습니다.
리눅스 커널 프로젝트 Contribution(기여)에 관심이 있는 분은 이 포스팅의 글을 참고하시면 좋을 것 같습니다.
(개인블로그)
http://rousalome.egloos.com/


제가 C언어를 몰라서 이 글타래를 이해는 못했지만,,
제가 C언어를 몰라서 이 글타래를 이해는 못했지만,,,
그 느낌만은 진짜 멋있습니다!!! 그저 순수하게 +1 좋아요를 누르고 싶어요!!!
리눅스를 좋아해주셔서 정말 감사드립니다^^^
[크롬북 우분투 18.04에서 댓글을 적었어요]
제 글에 응원주셔서 감사합니다..
이렇게 리눅스를 좋아하시는 분이 있어 기쁩니다.
(개인블로그)
http://rousalome.egloos.com
Gmane 에서 겨우 찾았어요 ;;;
진심으로 축하드립니다! 그리고 감사드립니다^^^
[크롬북 우분투 18.04에서 적었어요]
--
^고맙습니다 감사합니다_^))//
리눅스 커널 메일링 리스트 인증 샷이네요 ^^
제가 올린 패치의 리눅스 커널 메일링 리스트 '인증 샷'까지 올려주셨군요.
감사합니다.
(개인블로그)
http://rousalome.egloos.com
댓글 달기