Changeset View
Changeset View
Standalone View
Standalone View
sys/riscv/riscv/copyinout.S
Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
* a2 - Size of copy | * a2 - Size of copy | ||||
*/ | */ | ||||
.macro copycommon | .macro copycommon | ||||
la a6, copyio_fault /* Get the handler address */ | la a6, copyio_fault /* Get the handler address */ | ||||
SET_FAULT_HANDLER(a6, a7) /* Set the handler */ | SET_FAULT_HANDLER(a6, a7) /* Set the handler */ | ||||
ENTER_USER_ACCESS(a7) | ENTER_USER_ACCESS(a7) | ||||
li t2, XLEN_BYTES | li t2, XLEN_BYTES | ||||
blt a2, t2, 3f /* Byte-copy if len < XLEN_BYTES */ | blt a2, t2, 4f /* Byte-copy if len < XLEN_BYTES */ | ||||
/* | /* | ||||
* Compare lower bits of src and dest. | * Compare lower bits of src and dest. | ||||
* If they are aligned with each other, we can do word copy. | * If they are aligned with each other, we can do word copy. | ||||
*/ | */ | ||||
andi t0, a0, (XLEN_BYTES-1) /* Low bits of src */ | andi t0, a0, (XLEN_BYTES-1) /* Low bits of src */ | ||||
andi t1, a1, (XLEN_BYTES-1) /* Low bits of dest */ | andi t1, a1, (XLEN_BYTES-1) /* Low bits of dest */ | ||||
bne t0, t1, 3f /* Misaligned. Go to byte copy */ | bne t0, t1, 4f /* Misaligned. Go to byte copy */ | ||||
beqz t0, 2f /* Already word-aligned, skip ahead */ | beqz t0, 2f /* Already word-aligned, skip ahead */ | ||||
/* Byte copy until the first word-aligned address */ | /* Byte copy until the first word-aligned address */ | ||||
1: lb a4, 0(a0) /* Load byte from src */ | 1: lb a4, 0(a0) /* Load byte from src */ | ||||
addi a0, a0, 1 | addi a0, a0, 1 | ||||
sb a4, 0(a1) /* Store byte in dest */ | sb a4, 0(a1) /* Store byte in dest */ | ||||
addi a1, a1, 1 | addi a1, a1, 1 | ||||
addi a2, a2, -1 /* len-- */ | addi a2, a2, -1 /* len-- */ | ||||
andi t0, a0, (XLEN_BYTES-1) | andi t0, a0, (XLEN_BYTES-1) | ||||
bnez t0, 1b | bnez t0, 1b | ||||
j 3f | |||||
/* Copy words */ | /* Copy words */ | ||||
2: ld a4, 0(a0) /* Load word from src */ | 2: ld a4, 0(a0) /* Load word from src */ | ||||
addi a0, a0, XLEN_BYTES | addi a0, a0, XLEN_BYTES | ||||
sd a4, 0(a1) /* Store word in dest */ | sd a4, 0(a1) /* Store word in dest */ | ||||
addi a1, a1, XLEN_BYTES | addi a1, a1, XLEN_BYTES | ||||
addi a2, a2, -XLEN_BYTES /* len -= XLEN_BYTES */ | addi a2, a2, -XLEN_BYTES /* len -= XLEN_BYTES */ | ||||
bgeu a2, t2, 2b /* Again if len >= XLEN_BYTES */ | 3: bgeu a2, t2, 2b /* Again if len >= XLEN_BYTES */ | ||||
/* Check if we're finished */ | /* Check if we're finished */ | ||||
beqz a2, 4f | beqz a2, 5f | ||||
/* Copy any remaining bytes */ | /* Copy any remaining bytes */ | ||||
3: lb a4, 0(a0) /* Load byte from src */ | 4: lb a4, 0(a0) /* Load byte from src */ | ||||
addi a0, a0, 1 | addi a0, a0, 1 | ||||
sb a4, 0(a1) /* Store byte in dest */ | sb a4, 0(a1) /* Store byte in dest */ | ||||
addi a1, a1, 1 | addi a1, a1, 1 | ||||
addi a2, a2, -1 /* len-- */ | addi a2, a2, -1 /* len-- */ | ||||
bnez a2, 3b | bnez a2, 4b | ||||
4: EXIT_USER_ACCESS(a7) | 5: EXIT_USER_ACCESS(a7) | ||||
SET_FAULT_HANDLER(x0, a7) /* Clear the handler */ | SET_FAULT_HANDLER(x0, a7) /* Clear the handler */ | ||||
.endm | .endm | ||||
/* | /* | ||||
* Copies from a kernel to user address | * Copies from a kernel to user address | ||||
* | * | ||||
* int copyout(const void *kaddr, void *udaddr, size_t len) | * int copyout(const void *kaddr, void *udaddr, size_t len) | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 68 Lines • Show Last 20 Lines |