現在、デバイスドライバを作成しています。教育機器qemu(RISC-V)から。したがって、質問、すでに一つがあることを確認しました。デバイスドライバそのような機器の場合。
~によるとEduデバイスドキュメントのこの行これは、アドレス> = 0x80がサイズ== 4またはサイズ== 8アクセスを許可することを意味します。これらの制約を図に示します。ここはedu_mmio_read()
そしてここはedu_mmio_write()
Eduデバイスのソースコードから。
内部にドライバーコード、およびの場合、read()
8write()
バイトではなく4バイトサイズの読み取り/書き込み値のみを処理するようです。したがって、8バイトの値の読み書きをサポートするために、これら2つの関数に新しいものを追加しました。
static ssize_t read(struct file *filp, char __user *buf, size_t len, loff_t *off)
{
ssize_t ret;
u32 kbuf32;
u64 kbuf64;
if (*off % 4 || len == 0) {
ret = 0;
} else {
switch (len)
{
case 4:
kbuf32 = ioread32(mmio + *off);
if (copy_to_user(buf, (void *)&kbuf32, len)) {
ret = -EFAULT;
} else {
ret = 4;
(*off)++;
}
break;
case 8:
kbuf64 = ioread64(mmio + *off);
if (copy_to_user(buf, (void *)&kbuf64, len)) {
ret = -EFAULT;
} else {
ret = 8;
(*off)++;
}
break;
default:
ret = -EFAULT;
break;
}
}
return ret;
}
static ssize_t write(struct file *filp, const char __user *buf, size_t len, loff_t *off)
{
ssize_t ret;
u32 kbuf32; /* for size == 4 */
u64 kbuf64; /* for size == 8 */
ret = len;
if (!(*off % 4)) {
switch (len) {
case 4:
/* copy buf to kbuf32 */
if (copy_from_user((void *)&kbuf32, buf, len)) {
ret = -EFAULT;
} else {
iowrite32(kbuf32, mmio + *off);
}
break;
case 8:
if (copy_from_user((void *)&kbuf64, buf, len)) {
ret = -EFAULT;
} else {
iowrite64(kbuf64, mmio + *off);
}
break;
default:
ret = -EFAULT;
break;
}
}
return ret;
}
私のユーザーモードテストコードは次のことを行います。
// open the device - succeed
// fd2 - the file descriptor representing the opened edu device
uint64_t val64 = 0x8b320000; // a random 64-bit value
unsigned long ret = -1; // retval
// write val64 to 0x80
lseek(fd2, 0x80, SEEK_SET); // seek to address 0x80 - dma.src in edu device source code (line 281)
ret = write(fd2, &val64, sizeof(uint64_t));
if(ret == -1) printf("write to dma src failed\n");
else printf("written %llx to dma src\n", val64);
// reset val64
val64 = 0;
// read what we have just written (sanity check)
lseek(fd2, 0x80, SEEK_SET);
ret = read(fd2, &ret64, sizeof(uint64_t));
if(ret == -1) printf("read from dma src failed\n");
else printf("sanity check: read dma src and we get - %llx\n", ret64);
ちなみに、ユーザーモードコードをテストすると、アドレスに値が書き込まれますが、0x80
読み取ることはできません。いくつかのprintfステートメントを追加し、read()
次のコード行に対応するエラーが発生したことを確認しました。
kbuf64 = ioread64(mmio + *off);
私はこれを見つけましたページIOアクセス機能の違いについて話し、に置き換えioread64()
ましたが、readq()
まだ問題は解決されませんでした。kbuf64 = ioread64(mmio + *off);
実行中にコードの実行が停止します。追加も試しましたが、#define CONFIG_64BIT
まだエラーは解決されませんでした。
その後、Ctrl + Cを押してもユーザーモードコードを停止できません。私ができることは、QEMUを停止してCtrl + Aを押してからXを押して再起動することでした。
4バイト値の場合ioread32()
と一緒に読み取りまたは書き込みを使用できますiowrite32()
。
何が間違ってエラーが発生したのかわかりますかioread64()
?