kaist-cp / rv6

Other
125 stars 13 forks source link

When KVM enabled, x2 register value is changed after "hvc" assembly, but rustc doesn't notice it #605

Closed junsooo closed 2 years ago

junsooo commented 2 years ago

KVM enabled, opt-level > 1일 때 rv6를 실행하면, https://github.com/kaist-cp/rv6/blob/main/kernel-rs/src/arch/arm/start.rs#L46 해당 라인에 kernel_entry 값으로 원래는 0x40010000 값이 들어가야 합니다. for i == 1 일 때는 잘 들어갑니다. gdb를 보면 x2 register에 0x40010000 값이 들어가고, smc_call을 진행할 때 hvc assembly가 실행됩니다. 이후 x2 register 값은 0이 됩니다.

https://chasinglulu.github.io/downloads/ARM_DEN0028B_SMC_Calling_Convention.pdf 해당 문서 9쪽의 2.7 SMC64/HVC64 Argument passing 를 보면, Results are returned in X0-X3., Registers X18-X30 and stack pointers SP_EL0 and SP_ELx are saved by the function that is called, and must be preserved over the SMC or HVC call. 를 보았을 때 x0부터 x3 값을 rustc가 보존하도록 처리해야 합니다. 하지만 실제로는 그렇게 처리하지 않아 x2 값이 0으로 초기화되어서 for i == 2 일때 정상적으로 실행이 되지 않습니다.

따라서 이는 rustc의 버그로 보이고, 2022-02-22 nightly 버전에서도 fix되지 않은 것을 확인했습니다. 먼저 rv6 코드를 임시로 수정하고, rust repo에 bug report를 올려 수정된 이후에 해당 코드를 정상적으로 돌릴 수 있도록 해야합니다.

junsooo commented 2 years ago

잘못된 이슈였습니다. https://chasinglulu.github.io/downloads/ARM_DEN0028B_SMC_Calling_Convention.pdf 에 따라서 x0, x1, x2, x3이 return 돼야했는데, x1, x2, x3가 asm!에서 in()으로 정의돼있어서 컴파일러가 기존 값을 저장해야하는지 알수가 없었기 때문에 저장이 안된 것이었습니다.