All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] RISC-V: KVM: change get_reg/set_reg error codes
@ 2023-07-31 12:04 ` Daniel Henrique Barboza
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

Hi,

This work was motivated by the changes made in QEMU in commit df817297d7
("target/riscv: update multi-letter extension KVM properties") where it
was required to use EINVAL to try to assess whether a given extension is
available in the host.

It turns out that the RISC-V KVM module makes regular use of the EIVAL
error code in all kvm_get_one_reg() and kvm_set_one_reg() callbacks,
which is not ideal. For example, ENOENT is a better error code for the
case where a given register does not exist. While at it I decided to
take a look at other error codes from these callbacks, comparing them
with how other archs (ARM) handles the same error types, and changed
some of the EOPNOTSUPP instances to either ENOENT or EBUSY.

I am aware that changing error codes can be problematic to existing
userspaces. I took a look and no other major userspace (checked crosvm,
rust-vmm, QEMU, kvmtool), aside from QEMU now checking for EIVAL (and we
can't change that because of backwards compat for that particular case
we're covering), will be impacted by this kind of change since they're
all checking for "return < 0 then ..." instead of doing specific error
handling based on the error value. This means that we're still in good
time to make this kind of change while we're still in the initial steps
of the RISC-V KVM ecossystem support.

Patch 3 happens to also change the behavior of the set_reg() for
zicbom/zicboz block sizes. Instead of always erroring out we'll check if
userspace is writing the same value that the host uses. In this case,
allow the write to succeed (i.e. do nothing). This avoids the situation
in which userspace reads cbom_block_size, find out that it's set to X,
and then can't write the same value back to the register. It's a QOL
improvement to allow userspace to be lazier when reading/writing regs. A
similar change was also made in patch 4.

Patches are based on top of riscv_kvm_queue.

Daniel Henrique Barboza (6):
  RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
  RISC-V: KVM: use ENOENT in *_one_reg() when extension is unavailable
  RISC-V: KVM: do not EOPNOTSUPP in set_one_reg() zicbo(m|z)
  RISC-V: KVM: do not EOPNOTSUPP in set KVM_REG_RISCV_TIMER_REG
  RISC-V: KVM: use EBUSY when !vcpu->arch.ran_atleast_once
  docs: kvm: riscv: document EBUSY in KVM_SET_ONE_REG

 Documentation/virt/kvm/api.rst |  2 ++
 arch/riscv/kvm/aia.c           |  4 +--
 arch/riscv/kvm/vcpu_fp.c       | 12 ++++----
 arch/riscv/kvm/vcpu_onereg.c   | 52 ++++++++++++++++++++--------------
 arch/riscv/kvm/vcpu_sbi.c      | 16 ++++++-----
 arch/riscv/kvm/vcpu_timer.c    | 11 +++----
 6 files changed, 55 insertions(+), 42 deletions(-)

-- 
2.41.0


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 0/6] RISC-V: KVM: change get_reg/set_reg error codes
@ 2023-07-31 12:04 ` Daniel Henrique Barboza
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

Hi,

This work was motivated by the changes made in QEMU in commit df817297d7
("target/riscv: update multi-letter extension KVM properties") where it
was required to use EINVAL to try to assess whether a given extension is
available in the host.

It turns out that the RISC-V KVM module makes regular use of the EIVAL
error code in all kvm_get_one_reg() and kvm_set_one_reg() callbacks,
which is not ideal. For example, ENOENT is a better error code for the
case where a given register does not exist. While at it I decided to
take a look at other error codes from these callbacks, comparing them
with how other archs (ARM) handles the same error types, and changed
some of the EOPNOTSUPP instances to either ENOENT or EBUSY.

I am aware that changing error codes can be problematic to existing
userspaces. I took a look and no other major userspace (checked crosvm,
rust-vmm, QEMU, kvmtool), aside from QEMU now checking for EIVAL (and we
can't change that because of backwards compat for that particular case
we're covering), will be impacted by this kind of change since they're
all checking for "return < 0 then ..." instead of doing specific error
handling based on the error value. This means that we're still in good
time to make this kind of change while we're still in the initial steps
of the RISC-V KVM ecossystem support.

Patch 3 happens to also change the behavior of the set_reg() for
zicbom/zicboz block sizes. Instead of always erroring out we'll check if
userspace is writing the same value that the host uses. In this case,
allow the write to succeed (i.e. do nothing). This avoids the situation
in which userspace reads cbom_block_size, find out that it's set to X,
and then can't write the same value back to the register. It's a QOL
improvement to allow userspace to be lazier when reading/writing regs. A
similar change was also made in patch 4.

Patches are based on top of riscv_kvm_queue.

Daniel Henrique Barboza (6):
  RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
  RISC-V: KVM: use ENOENT in *_one_reg() when extension is unavailable
  RISC-V: KVM: do not EOPNOTSUPP in set_one_reg() zicbo(m|z)
  RISC-V: KVM: do not EOPNOTSUPP in set KVM_REG_RISCV_TIMER_REG
  RISC-V: KVM: use EBUSY when !vcpu->arch.ran_atleast_once
  docs: kvm: riscv: document EBUSY in KVM_SET_ONE_REG

 Documentation/virt/kvm/api.rst |  2 ++
 arch/riscv/kvm/aia.c           |  4 +--
 arch/riscv/kvm/vcpu_fp.c       | 12 ++++----
 arch/riscv/kvm/vcpu_onereg.c   | 52 ++++++++++++++++++++--------------
 arch/riscv/kvm/vcpu_sbi.c      | 16 ++++++-----
 arch/riscv/kvm/vcpu_timer.c    | 11 +++----
 6 files changed, 55 insertions(+), 42 deletions(-)

-- 
2.41.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 1/6] RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
  2023-07-31 12:04 ` Daniel Henrique Barboza
@ 2023-07-31 12:04   ` Daniel Henrique Barboza
  -1 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

get_one_reg() and set_one_reg() are returning EINVAL errors for almost
everything: if a reg doesn't exist, if a reg ID is malformatted, if the
associated CPU extension that implements the reg isn't present in the
host, and for set_one_reg() if the value being written is invalid.

This isn't wrong according to the existing KVM API docs (EINVAL can be
used when there's no such register) but adding more ENOENT instances
will make easier for userspace to understand what went wrong.

Existing userspaces can be affected by this error code change. We
checked a few. As of current upstream code, crosvm doesn't check for any
particular errno code when using kvm_(get|set)_one_reg(). Neither does
QEMU. rust-vmm doesn't have kvm-riscv support yet. Thus we have a good
chance of changing these error codes now while the KVM RISC-V ecosystem
is still new, minimizing user impact.

Change all get_one_reg() and set_one_reg() implementations to return
-ENOENT at all "no such register" cases.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 arch/riscv/kvm/aia.c         |  4 ++--
 arch/riscv/kvm/vcpu_fp.c     | 12 ++++++------
 arch/riscv/kvm/vcpu_onereg.c | 30 +++++++++++++++---------------
 arch/riscv/kvm/vcpu_sbi.c    | 16 +++++++++-------
 arch/riscv/kvm/vcpu_timer.c  |  8 ++++----
 5 files changed, 36 insertions(+), 34 deletions(-)

diff --git a/arch/riscv/kvm/aia.c b/arch/riscv/kvm/aia.c
index 585a3b42c52c..74bb27440527 100644
--- a/arch/riscv/kvm/aia.c
+++ b/arch/riscv/kvm/aia.c
@@ -176,7 +176,7 @@ int kvm_riscv_vcpu_aia_get_csr(struct kvm_vcpu *vcpu,
 	struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
 
 	if (reg_num >= sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long))
-		return -EINVAL;
+		return -ENOENT;
 
 	*out_val = 0;
 	if (kvm_riscv_aia_available())
@@ -192,7 +192,7 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
 	struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
 
 	if (reg_num >= sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long))
-		return -EINVAL;
+		return -ENOENT;
 
 	if (kvm_riscv_aia_available()) {
 		((unsigned long *)csr)[reg_num] = val;
diff --git a/arch/riscv/kvm/vcpu_fp.c b/arch/riscv/kvm/vcpu_fp.c
index 9d8cbc42057a..08ba48a395aa 100644
--- a/arch/riscv/kvm/vcpu_fp.c
+++ b/arch/riscv/kvm/vcpu_fp.c
@@ -96,7 +96,7 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu,
 			  reg_num <= KVM_REG_RISCV_FP_F_REG(f[31]))
 			reg_val = &cntx->fp.f.f[reg_num];
 		else
-			return -EINVAL;
+			return -ENOENT;
 	} else if ((rtype == KVM_REG_RISCV_FP_D) &&
 		   riscv_isa_extension_available(vcpu->arch.isa, d)) {
 		if (reg_num == KVM_REG_RISCV_FP_D_REG(fcsr)) {
@@ -109,9 +109,9 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu,
 				return -EINVAL;
 			reg_val = &cntx->fp.d.f[reg_num];
 		} else
-			return -EINVAL;
+			return -ENOENT;
 	} else
-		return -EINVAL;
+		return -ENOENT;
 
 	if (copy_to_user(uaddr, reg_val, KVM_REG_SIZE(reg->id)))
 		return -EFAULT;
@@ -141,7 +141,7 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu,
 			  reg_num <= KVM_REG_RISCV_FP_F_REG(f[31]))
 			reg_val = &cntx->fp.f.f[reg_num];
 		else
-			return -EINVAL;
+			return -ENOENT;
 	} else if ((rtype == KVM_REG_RISCV_FP_D) &&
 		   riscv_isa_extension_available(vcpu->arch.isa, d)) {
 		if (reg_num == KVM_REG_RISCV_FP_D_REG(fcsr)) {
@@ -154,9 +154,9 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu,
 				return -EINVAL;
 			reg_val = &cntx->fp.d.f[reg_num];
 		} else
-			return -EINVAL;
+			return -ENOENT;
 	} else
-		return -EINVAL;
+		return -ENOENT;
 
 	if (copy_from_user(reg_val, uaddr, KVM_REG_SIZE(reg->id)))
 		return -EFAULT;
diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index 0dc2c2cecb45..ba63522be060 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -153,7 +153,7 @@ static int kvm_riscv_vcpu_get_reg_config(struct kvm_vcpu *vcpu,
 		reg_val = vcpu->arch.mimpid;
 		break;
 	default:
-		return -EINVAL;
+		return -ENOENT;
 	}
 
 	if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
@@ -235,7 +235,7 @@ static int kvm_riscv_vcpu_set_reg_config(struct kvm_vcpu *vcpu,
 			return -EBUSY;
 		break;
 	default:
-		return -EINVAL;
+		return -ENOENT;
 	}
 
 	return 0;
@@ -255,7 +255,7 @@ static int kvm_riscv_vcpu_get_reg_core(struct kvm_vcpu *vcpu,
 	if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
 		return -EINVAL;
 	if (reg_num >= sizeof(struct kvm_riscv_core) / sizeof(unsigned long))
-		return -EINVAL;
+		return -ENOENT;
 
 	if (reg_num == KVM_REG_RISCV_CORE_REG(regs.pc))
 		reg_val = cntx->sepc;
@@ -266,7 +266,7 @@ static int kvm_riscv_vcpu_get_reg_core(struct kvm_vcpu *vcpu,
 		reg_val = (cntx->sstatus & SR_SPP) ?
 				KVM_RISCV_MODE_S : KVM_RISCV_MODE_U;
 	else
-		return -EINVAL;
+		return -ENOENT;
 
 	if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
 		return -EFAULT;
@@ -288,7 +288,7 @@ static int kvm_riscv_vcpu_set_reg_core(struct kvm_vcpu *vcpu,
 	if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
 		return -EINVAL;
 	if (reg_num >= sizeof(struct kvm_riscv_core) / sizeof(unsigned long))
-		return -EINVAL;
+		return -ENOENT;
 
 	if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id)))
 		return -EFAULT;
@@ -304,7 +304,7 @@ static int kvm_riscv_vcpu_set_reg_core(struct kvm_vcpu *vcpu,
 		else
 			cntx->sstatus &= ~SR_SPP;
 	} else
-		return -EINVAL;
+		return -ENOENT;
 
 	return 0;
 }
@@ -316,7 +316,7 @@ static int kvm_riscv_vcpu_general_get_csr(struct kvm_vcpu *vcpu,
 	struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
 
 	if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
-		return -EINVAL;
+		return -ENOENT;
 
 	if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
 		kvm_riscv_vcpu_flush_interrupts(vcpu);
@@ -335,7 +335,7 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
 	struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
 
 	if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
-		return -EINVAL;
+		return -ENOENT;
 
 	if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
 		reg_val &= VSIP_VALID_MASK;
@@ -374,7 +374,7 @@ static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu,
 		rc = kvm_riscv_vcpu_aia_get_csr(vcpu, reg_num, &reg_val);
 		break;
 	default:
-		rc = -EINVAL;
+		rc = -ENOENT;
 		break;
 	}
 	if (rc)
@@ -413,7 +413,7 @@ static int kvm_riscv_vcpu_set_reg_csr(struct kvm_vcpu *vcpu,
 		rc = kvm_riscv_vcpu_aia_set_csr(vcpu, reg_num, reg_val);
 		break;
 	default:
-		rc = -EINVAL;
+		rc = -ENOENT;
 		break;
 	}
 	if (rc)
@@ -430,7 +430,7 @@ static int riscv_vcpu_get_isa_ext_single(struct kvm_vcpu *vcpu,
 
 	if (reg_num >= KVM_RISCV_ISA_EXT_MAX ||
 	    reg_num >= ARRAY_SIZE(kvm_isa_ext_arr))
-		return -EINVAL;
+		return -ENOENT;
 
 	*reg_val = 0;
 	host_isa_ext = kvm_isa_ext_arr[reg_num];
@@ -448,7 +448,7 @@ static int riscv_vcpu_set_isa_ext_single(struct kvm_vcpu *vcpu,
 
 	if (reg_num >= KVM_RISCV_ISA_EXT_MAX ||
 	    reg_num >= ARRAY_SIZE(kvm_isa_ext_arr))
-		return -EINVAL;
+		return -ENOENT;
 
 	host_isa_ext = kvm_isa_ext_arr[reg_num];
 	if (!__riscv_isa_extension_available(NULL, host_isa_ext))
@@ -547,7 +547,7 @@ static int kvm_riscv_vcpu_get_reg_isa_ext(struct kvm_vcpu *vcpu,
 			reg_val = ~reg_val;
 		break;
 	default:
-		rc = -EINVAL;
+		rc = -ENOENT;
 	}
 	if (rc)
 		return rc;
@@ -585,7 +585,7 @@ static int kvm_riscv_vcpu_set_reg_isa_ext(struct kvm_vcpu *vcpu,
 	case KVM_REG_RISCV_SBI_MULTI_DIS:
 		return riscv_vcpu_set_isa_ext_multi(vcpu, reg_num, reg_val, false);
 	default:
-		return -EINVAL;
+		return -ENOENT;
 	}
 
 	return 0;
@@ -652,5 +652,5 @@ int kvm_riscv_vcpu_get_reg(struct kvm_vcpu *vcpu,
 		break;
 	}
 
-	return -EINVAL;
+	return -ENOENT;
 }
diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c
index 7b46e04fb667..9cd97091c723 100644
--- a/arch/riscv/kvm/vcpu_sbi.c
+++ b/arch/riscv/kvm/vcpu_sbi.c
@@ -140,8 +140,10 @@ static int riscv_vcpu_set_sbi_ext_single(struct kvm_vcpu *vcpu,
 	const struct kvm_riscv_sbi_extension_entry *sext = NULL;
 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
 
-	if (reg_num >= KVM_RISCV_SBI_EXT_MAX ||
-	    (reg_val != 1 && reg_val != 0))
+	if (reg_num >= KVM_RISCV_SBI_EXT_MAX)
+		return -ENOENT;
+
+	if (reg_val != 1 && reg_val != 0)
 		return -EINVAL;
 
 	for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
@@ -175,7 +177,7 @@ static int riscv_vcpu_get_sbi_ext_single(struct kvm_vcpu *vcpu,
 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
 
 	if (reg_num >= KVM_RISCV_SBI_EXT_MAX)
-		return -EINVAL;
+		return -ENOENT;
 
 	for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
 		if (sbi_ext[i].ext_idx == reg_num) {
@@ -206,7 +208,7 @@ static int riscv_vcpu_set_sbi_ext_multi(struct kvm_vcpu *vcpu,
 	unsigned long i, ext_id;
 
 	if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST)
-		return -EINVAL;
+		return -ENOENT;
 
 	for_each_set_bit(i, &reg_val, BITS_PER_LONG) {
 		ext_id = i + reg_num * BITS_PER_LONG;
@@ -226,7 +228,7 @@ static int riscv_vcpu_get_sbi_ext_multi(struct kvm_vcpu *vcpu,
 	unsigned long i, ext_id, ext_val;
 
 	if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST)
-		return -EINVAL;
+		return -ENOENT;
 
 	for (i = 0; i < BITS_PER_LONG; i++) {
 		ext_id = i + reg_num * BITS_PER_LONG;
@@ -272,7 +274,7 @@ int kvm_riscv_vcpu_set_reg_sbi_ext(struct kvm_vcpu *vcpu,
 	case KVM_REG_RISCV_SBI_MULTI_DIS:
 		return riscv_vcpu_set_sbi_ext_multi(vcpu, reg_num, reg_val, false);
 	default:
-		return -EINVAL;
+		return -ENOENT;
 	}
 
 	return 0;
@@ -307,7 +309,7 @@ int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu,
 			reg_val = ~reg_val;
 		break;
 	default:
-		rc = -EINVAL;
+		rc = -ENOENT;
 	}
 	if (rc)
 		return rc;
diff --git a/arch/riscv/kvm/vcpu_timer.c b/arch/riscv/kvm/vcpu_timer.c
index 3ac2ff6a65da..527d269cafff 100644
--- a/arch/riscv/kvm/vcpu_timer.c
+++ b/arch/riscv/kvm/vcpu_timer.c
@@ -170,7 +170,7 @@ int kvm_riscv_vcpu_get_reg_timer(struct kvm_vcpu *vcpu,
 	if (KVM_REG_SIZE(reg->id) != sizeof(u64))
 		return -EINVAL;
 	if (reg_num >= sizeof(struct kvm_riscv_timer) / sizeof(u64))
-		return -EINVAL;
+		return -ENOENT;
 
 	switch (reg_num) {
 	case KVM_REG_RISCV_TIMER_REG(frequency):
@@ -187,7 +187,7 @@ int kvm_riscv_vcpu_get_reg_timer(struct kvm_vcpu *vcpu,
 					  KVM_RISCV_TIMER_STATE_OFF;
 		break;
 	default:
-		return -EINVAL;
+		return -ENOENT;
 	}
 
 	if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
@@ -211,7 +211,7 @@ int kvm_riscv_vcpu_set_reg_timer(struct kvm_vcpu *vcpu,
 	if (KVM_REG_SIZE(reg->id) != sizeof(u64))
 		return -EINVAL;
 	if (reg_num >= sizeof(struct kvm_riscv_timer) / sizeof(u64))
-		return -EINVAL;
+		return -ENOENT;
 
 	if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id)))
 		return -EFAULT;
@@ -233,7 +233,7 @@ int kvm_riscv_vcpu_set_reg_timer(struct kvm_vcpu *vcpu,
 			ret = kvm_riscv_vcpu_timer_cancel(t);
 		break;
 	default:
-		ret = -EINVAL;
+		ret = -ENOENT;
 		break;
 	}
 
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 1/6] RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
@ 2023-07-31 12:04   ` Daniel Henrique Barboza
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

get_one_reg() and set_one_reg() are returning EINVAL errors for almost
everything: if a reg doesn't exist, if a reg ID is malformatted, if the
associated CPU extension that implements the reg isn't present in the
host, and for set_one_reg() if the value being written is invalid.

This isn't wrong according to the existing KVM API docs (EINVAL can be
used when there's no such register) but adding more ENOENT instances
will make easier for userspace to understand what went wrong.

Existing userspaces can be affected by this error code change. We
checked a few. As of current upstream code, crosvm doesn't check for any
particular errno code when using kvm_(get|set)_one_reg(). Neither does
QEMU. rust-vmm doesn't have kvm-riscv support yet. Thus we have a good
chance of changing these error codes now while the KVM RISC-V ecosystem
is still new, minimizing user impact.

Change all get_one_reg() and set_one_reg() implementations to return
-ENOENT at all "no such register" cases.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 arch/riscv/kvm/aia.c         |  4 ++--
 arch/riscv/kvm/vcpu_fp.c     | 12 ++++++------
 arch/riscv/kvm/vcpu_onereg.c | 30 +++++++++++++++---------------
 arch/riscv/kvm/vcpu_sbi.c    | 16 +++++++++-------
 arch/riscv/kvm/vcpu_timer.c  |  8 ++++----
 5 files changed, 36 insertions(+), 34 deletions(-)

diff --git a/arch/riscv/kvm/aia.c b/arch/riscv/kvm/aia.c
index 585a3b42c52c..74bb27440527 100644
--- a/arch/riscv/kvm/aia.c
+++ b/arch/riscv/kvm/aia.c
@@ -176,7 +176,7 @@ int kvm_riscv_vcpu_aia_get_csr(struct kvm_vcpu *vcpu,
 	struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
 
 	if (reg_num >= sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long))
-		return -EINVAL;
+		return -ENOENT;
 
 	*out_val = 0;
 	if (kvm_riscv_aia_available())
@@ -192,7 +192,7 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
 	struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
 
 	if (reg_num >= sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long))
-		return -EINVAL;
+		return -ENOENT;
 
 	if (kvm_riscv_aia_available()) {
 		((unsigned long *)csr)[reg_num] = val;
diff --git a/arch/riscv/kvm/vcpu_fp.c b/arch/riscv/kvm/vcpu_fp.c
index 9d8cbc42057a..08ba48a395aa 100644
--- a/arch/riscv/kvm/vcpu_fp.c
+++ b/arch/riscv/kvm/vcpu_fp.c
@@ -96,7 +96,7 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu,
 			  reg_num <= KVM_REG_RISCV_FP_F_REG(f[31]))
 			reg_val = &cntx->fp.f.f[reg_num];
 		else
-			return -EINVAL;
+			return -ENOENT;
 	} else if ((rtype == KVM_REG_RISCV_FP_D) &&
 		   riscv_isa_extension_available(vcpu->arch.isa, d)) {
 		if (reg_num == KVM_REG_RISCV_FP_D_REG(fcsr)) {
@@ -109,9 +109,9 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu,
 				return -EINVAL;
 			reg_val = &cntx->fp.d.f[reg_num];
 		} else
-			return -EINVAL;
+			return -ENOENT;
 	} else
-		return -EINVAL;
+		return -ENOENT;
 
 	if (copy_to_user(uaddr, reg_val, KVM_REG_SIZE(reg->id)))
 		return -EFAULT;
@@ -141,7 +141,7 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu,
 			  reg_num <= KVM_REG_RISCV_FP_F_REG(f[31]))
 			reg_val = &cntx->fp.f.f[reg_num];
 		else
-			return -EINVAL;
+			return -ENOENT;
 	} else if ((rtype == KVM_REG_RISCV_FP_D) &&
 		   riscv_isa_extension_available(vcpu->arch.isa, d)) {
 		if (reg_num == KVM_REG_RISCV_FP_D_REG(fcsr)) {
@@ -154,9 +154,9 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu,
 				return -EINVAL;
 			reg_val = &cntx->fp.d.f[reg_num];
 		} else
-			return -EINVAL;
+			return -ENOENT;
 	} else
-		return -EINVAL;
+		return -ENOENT;
 
 	if (copy_from_user(reg_val, uaddr, KVM_REG_SIZE(reg->id)))
 		return -EFAULT;
diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index 0dc2c2cecb45..ba63522be060 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -153,7 +153,7 @@ static int kvm_riscv_vcpu_get_reg_config(struct kvm_vcpu *vcpu,
 		reg_val = vcpu->arch.mimpid;
 		break;
 	default:
-		return -EINVAL;
+		return -ENOENT;
 	}
 
 	if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
@@ -235,7 +235,7 @@ static int kvm_riscv_vcpu_set_reg_config(struct kvm_vcpu *vcpu,
 			return -EBUSY;
 		break;
 	default:
-		return -EINVAL;
+		return -ENOENT;
 	}
 
 	return 0;
@@ -255,7 +255,7 @@ static int kvm_riscv_vcpu_get_reg_core(struct kvm_vcpu *vcpu,
 	if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
 		return -EINVAL;
 	if (reg_num >= sizeof(struct kvm_riscv_core) / sizeof(unsigned long))
-		return -EINVAL;
+		return -ENOENT;
 
 	if (reg_num == KVM_REG_RISCV_CORE_REG(regs.pc))
 		reg_val = cntx->sepc;
@@ -266,7 +266,7 @@ static int kvm_riscv_vcpu_get_reg_core(struct kvm_vcpu *vcpu,
 		reg_val = (cntx->sstatus & SR_SPP) ?
 				KVM_RISCV_MODE_S : KVM_RISCV_MODE_U;
 	else
-		return -EINVAL;
+		return -ENOENT;
 
 	if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
 		return -EFAULT;
@@ -288,7 +288,7 @@ static int kvm_riscv_vcpu_set_reg_core(struct kvm_vcpu *vcpu,
 	if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
 		return -EINVAL;
 	if (reg_num >= sizeof(struct kvm_riscv_core) / sizeof(unsigned long))
-		return -EINVAL;
+		return -ENOENT;
 
 	if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id)))
 		return -EFAULT;
@@ -304,7 +304,7 @@ static int kvm_riscv_vcpu_set_reg_core(struct kvm_vcpu *vcpu,
 		else
 			cntx->sstatus &= ~SR_SPP;
 	} else
-		return -EINVAL;
+		return -ENOENT;
 
 	return 0;
 }
@@ -316,7 +316,7 @@ static int kvm_riscv_vcpu_general_get_csr(struct kvm_vcpu *vcpu,
 	struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
 
 	if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
-		return -EINVAL;
+		return -ENOENT;
 
 	if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
 		kvm_riscv_vcpu_flush_interrupts(vcpu);
@@ -335,7 +335,7 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
 	struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
 
 	if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
-		return -EINVAL;
+		return -ENOENT;
 
 	if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
 		reg_val &= VSIP_VALID_MASK;
@@ -374,7 +374,7 @@ static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu,
 		rc = kvm_riscv_vcpu_aia_get_csr(vcpu, reg_num, &reg_val);
 		break;
 	default:
-		rc = -EINVAL;
+		rc = -ENOENT;
 		break;
 	}
 	if (rc)
@@ -413,7 +413,7 @@ static int kvm_riscv_vcpu_set_reg_csr(struct kvm_vcpu *vcpu,
 		rc = kvm_riscv_vcpu_aia_set_csr(vcpu, reg_num, reg_val);
 		break;
 	default:
-		rc = -EINVAL;
+		rc = -ENOENT;
 		break;
 	}
 	if (rc)
@@ -430,7 +430,7 @@ static int riscv_vcpu_get_isa_ext_single(struct kvm_vcpu *vcpu,
 
 	if (reg_num >= KVM_RISCV_ISA_EXT_MAX ||
 	    reg_num >= ARRAY_SIZE(kvm_isa_ext_arr))
-		return -EINVAL;
+		return -ENOENT;
 
 	*reg_val = 0;
 	host_isa_ext = kvm_isa_ext_arr[reg_num];
@@ -448,7 +448,7 @@ static int riscv_vcpu_set_isa_ext_single(struct kvm_vcpu *vcpu,
 
 	if (reg_num >= KVM_RISCV_ISA_EXT_MAX ||
 	    reg_num >= ARRAY_SIZE(kvm_isa_ext_arr))
-		return -EINVAL;
+		return -ENOENT;
 
 	host_isa_ext = kvm_isa_ext_arr[reg_num];
 	if (!__riscv_isa_extension_available(NULL, host_isa_ext))
@@ -547,7 +547,7 @@ static int kvm_riscv_vcpu_get_reg_isa_ext(struct kvm_vcpu *vcpu,
 			reg_val = ~reg_val;
 		break;
 	default:
-		rc = -EINVAL;
+		rc = -ENOENT;
 	}
 	if (rc)
 		return rc;
@@ -585,7 +585,7 @@ static int kvm_riscv_vcpu_set_reg_isa_ext(struct kvm_vcpu *vcpu,
 	case KVM_REG_RISCV_SBI_MULTI_DIS:
 		return riscv_vcpu_set_isa_ext_multi(vcpu, reg_num, reg_val, false);
 	default:
-		return -EINVAL;
+		return -ENOENT;
 	}
 
 	return 0;
@@ -652,5 +652,5 @@ int kvm_riscv_vcpu_get_reg(struct kvm_vcpu *vcpu,
 		break;
 	}
 
-	return -EINVAL;
+	return -ENOENT;
 }
diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c
index 7b46e04fb667..9cd97091c723 100644
--- a/arch/riscv/kvm/vcpu_sbi.c
+++ b/arch/riscv/kvm/vcpu_sbi.c
@@ -140,8 +140,10 @@ static int riscv_vcpu_set_sbi_ext_single(struct kvm_vcpu *vcpu,
 	const struct kvm_riscv_sbi_extension_entry *sext = NULL;
 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
 
-	if (reg_num >= KVM_RISCV_SBI_EXT_MAX ||
-	    (reg_val != 1 && reg_val != 0))
+	if (reg_num >= KVM_RISCV_SBI_EXT_MAX)
+		return -ENOENT;
+
+	if (reg_val != 1 && reg_val != 0)
 		return -EINVAL;
 
 	for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
@@ -175,7 +177,7 @@ static int riscv_vcpu_get_sbi_ext_single(struct kvm_vcpu *vcpu,
 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
 
 	if (reg_num >= KVM_RISCV_SBI_EXT_MAX)
-		return -EINVAL;
+		return -ENOENT;
 
 	for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
 		if (sbi_ext[i].ext_idx == reg_num) {
@@ -206,7 +208,7 @@ static int riscv_vcpu_set_sbi_ext_multi(struct kvm_vcpu *vcpu,
 	unsigned long i, ext_id;
 
 	if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST)
-		return -EINVAL;
+		return -ENOENT;
 
 	for_each_set_bit(i, &reg_val, BITS_PER_LONG) {
 		ext_id = i + reg_num * BITS_PER_LONG;
@@ -226,7 +228,7 @@ static int riscv_vcpu_get_sbi_ext_multi(struct kvm_vcpu *vcpu,
 	unsigned long i, ext_id, ext_val;
 
 	if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST)
-		return -EINVAL;
+		return -ENOENT;
 
 	for (i = 0; i < BITS_PER_LONG; i++) {
 		ext_id = i + reg_num * BITS_PER_LONG;
@@ -272,7 +274,7 @@ int kvm_riscv_vcpu_set_reg_sbi_ext(struct kvm_vcpu *vcpu,
 	case KVM_REG_RISCV_SBI_MULTI_DIS:
 		return riscv_vcpu_set_sbi_ext_multi(vcpu, reg_num, reg_val, false);
 	default:
-		return -EINVAL;
+		return -ENOENT;
 	}
 
 	return 0;
@@ -307,7 +309,7 @@ int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu,
 			reg_val = ~reg_val;
 		break;
 	default:
-		rc = -EINVAL;
+		rc = -ENOENT;
 	}
 	if (rc)
 		return rc;
diff --git a/arch/riscv/kvm/vcpu_timer.c b/arch/riscv/kvm/vcpu_timer.c
index 3ac2ff6a65da..527d269cafff 100644
--- a/arch/riscv/kvm/vcpu_timer.c
+++ b/arch/riscv/kvm/vcpu_timer.c
@@ -170,7 +170,7 @@ int kvm_riscv_vcpu_get_reg_timer(struct kvm_vcpu *vcpu,
 	if (KVM_REG_SIZE(reg->id) != sizeof(u64))
 		return -EINVAL;
 	if (reg_num >= sizeof(struct kvm_riscv_timer) / sizeof(u64))
-		return -EINVAL;
+		return -ENOENT;
 
 	switch (reg_num) {
 	case KVM_REG_RISCV_TIMER_REG(frequency):
@@ -187,7 +187,7 @@ int kvm_riscv_vcpu_get_reg_timer(struct kvm_vcpu *vcpu,
 					  KVM_RISCV_TIMER_STATE_OFF;
 		break;
 	default:
-		return -EINVAL;
+		return -ENOENT;
 	}
 
 	if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
@@ -211,7 +211,7 @@ int kvm_riscv_vcpu_set_reg_timer(struct kvm_vcpu *vcpu,
 	if (KVM_REG_SIZE(reg->id) != sizeof(u64))
 		return -EINVAL;
 	if (reg_num >= sizeof(struct kvm_riscv_timer) / sizeof(u64))
-		return -EINVAL;
+		return -ENOENT;
 
 	if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id)))
 		return -EFAULT;
@@ -233,7 +233,7 @@ int kvm_riscv_vcpu_set_reg_timer(struct kvm_vcpu *vcpu,
 			ret = kvm_riscv_vcpu_timer_cancel(t);
 		break;
 	default:
-		ret = -EINVAL;
+		ret = -ENOENT;
 		break;
 	}
 
-- 
2.41.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 2/6] RISC-V: KVM: use ENOENT in *_one_reg() when extension is unavailable
  2023-07-31 12:04 ` Daniel Henrique Barboza
@ 2023-07-31 12:04   ` Daniel Henrique Barboza
  -1 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

Following a similar logic as the previous patch let's minimize the EINVAL
usage in *_one_reg() APIs by using ENOENT when an extension that
implements the reg is not available.

For consistency we're also replacing an EOPNOTSUPP instance that should
be an ENOENT since it's an "extension is not available" error.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 arch/riscv/kvm/vcpu_onereg.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index ba63522be060..e630a68e4f27 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -135,12 +135,12 @@ static int kvm_riscv_vcpu_get_reg_config(struct kvm_vcpu *vcpu,
 		break;
 	case KVM_REG_RISCV_CONFIG_REG(zicbom_block_size):
 		if (!riscv_isa_extension_available(vcpu->arch.isa, ZICBOM))
-			return -EINVAL;
+			return -ENOENT;
 		reg_val = riscv_cbom_block_size;
 		break;
 	case KVM_REG_RISCV_CONFIG_REG(zicboz_block_size):
 		if (!riscv_isa_extension_available(vcpu->arch.isa, ZICBOZ))
-			return -EINVAL;
+			return -ENOENT;
 		reg_val = riscv_cboz_block_size;
 		break;
 	case KVM_REG_RISCV_CONFIG_REG(mvendorid):
@@ -452,7 +452,7 @@ static int riscv_vcpu_set_isa_ext_single(struct kvm_vcpu *vcpu,
 
 	host_isa_ext = kvm_isa_ext_arr[reg_num];
 	if (!__riscv_isa_extension_available(NULL, host_isa_ext))
-		return	-EOPNOTSUPP;
+		return	-ENOENT;
 
 	if (!vcpu->arch.ran_atleast_once) {
 		/*
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 2/6] RISC-V: KVM: use ENOENT in *_one_reg() when extension is unavailable
@ 2023-07-31 12:04   ` Daniel Henrique Barboza
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

Following a similar logic as the previous patch let's minimize the EINVAL
usage in *_one_reg() APIs by using ENOENT when an extension that
implements the reg is not available.

For consistency we're also replacing an EOPNOTSUPP instance that should
be an ENOENT since it's an "extension is not available" error.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 arch/riscv/kvm/vcpu_onereg.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index ba63522be060..e630a68e4f27 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -135,12 +135,12 @@ static int kvm_riscv_vcpu_get_reg_config(struct kvm_vcpu *vcpu,
 		break;
 	case KVM_REG_RISCV_CONFIG_REG(zicbom_block_size):
 		if (!riscv_isa_extension_available(vcpu->arch.isa, ZICBOM))
-			return -EINVAL;
+			return -ENOENT;
 		reg_val = riscv_cbom_block_size;
 		break;
 	case KVM_REG_RISCV_CONFIG_REG(zicboz_block_size):
 		if (!riscv_isa_extension_available(vcpu->arch.isa, ZICBOZ))
-			return -EINVAL;
+			return -ENOENT;
 		reg_val = riscv_cboz_block_size;
 		break;
 	case KVM_REG_RISCV_CONFIG_REG(mvendorid):
@@ -452,7 +452,7 @@ static int riscv_vcpu_set_isa_ext_single(struct kvm_vcpu *vcpu,
 
 	host_isa_ext = kvm_isa_ext_arr[reg_num];
 	if (!__riscv_isa_extension_available(NULL, host_isa_ext))
-		return	-EOPNOTSUPP;
+		return	-ENOENT;
 
 	if (!vcpu->arch.ran_atleast_once) {
 		/*
-- 
2.41.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 3/6] RISC-V: KVM: do not EOPNOTSUPP in set_one_reg() zicbo(m|z)
  2023-07-31 12:04 ` Daniel Henrique Barboza
@ 2023-07-31 12:04   ` Daniel Henrique Barboza
  -1 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

zicbom_block_size and zicboz_block_size have a peculiar API: they can be
read via get_one_reg() but any write will return a EOPNOTSUPP.

It makes sense to return a 'not supported' error since both values can't
be changed, but as far as userspace goes they're regs that are throwing
the same EOPNOTSUPP error even if they were read beforehand via
get_one_reg(), even if the same  read value is being written back.
EOPNOTSUPP is also returned even if ZICBOM/ZICBOZ aren't enabled in the
host.

Change both to work more like their counterparts in get_one_reg() and
return -ENOENT if their respective extensions aren't available. After
that, check if the userspace is written a valid value (i.e. the host
value). Throw an -EINVAL if that's not case, let it slide otherwise.

This allows both regs to be read/written by userspace in a 'lazy'
manner, as long as the userspace doesn't change the reg vals.

Suggested-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 arch/riscv/kvm/vcpu_onereg.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index e630a68e4f27..42bf01ab6a8f 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -213,9 +213,17 @@ static int kvm_riscv_vcpu_set_reg_config(struct kvm_vcpu *vcpu,
 		}
 		break;
 	case KVM_REG_RISCV_CONFIG_REG(zicbom_block_size):
-		return -EOPNOTSUPP;
+		if (!riscv_isa_extension_available(vcpu->arch.isa, ZICBOM))
+			return -ENOENT;
+		if (reg_val != riscv_cbom_block_size)
+			return -EINVAL;
+		break;
 	case KVM_REG_RISCV_CONFIG_REG(zicboz_block_size):
-		return -EOPNOTSUPP;
+		if (!riscv_isa_extension_available(vcpu->arch.isa, ZICBOZ))
+			return -ENOENT;
+		if (reg_val != riscv_cboz_block_size)
+			return -EINVAL;
+		break;
 	case KVM_REG_RISCV_CONFIG_REG(mvendorid):
 		if (!vcpu->arch.ran_atleast_once)
 			vcpu->arch.mvendorid = reg_val;
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 3/6] RISC-V: KVM: do not EOPNOTSUPP in set_one_reg() zicbo(m|z)
@ 2023-07-31 12:04   ` Daniel Henrique Barboza
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

zicbom_block_size and zicboz_block_size have a peculiar API: they can be
read via get_one_reg() but any write will return a EOPNOTSUPP.

It makes sense to return a 'not supported' error since both values can't
be changed, but as far as userspace goes they're regs that are throwing
the same EOPNOTSUPP error even if they were read beforehand via
get_one_reg(), even if the same  read value is being written back.
EOPNOTSUPP is also returned even if ZICBOM/ZICBOZ aren't enabled in the
host.

Change both to work more like their counterparts in get_one_reg() and
return -ENOENT if their respective extensions aren't available. After
that, check if the userspace is written a valid value (i.e. the host
value). Throw an -EINVAL if that's not case, let it slide otherwise.

This allows both regs to be read/written by userspace in a 'lazy'
manner, as long as the userspace doesn't change the reg vals.

Suggested-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 arch/riscv/kvm/vcpu_onereg.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index e630a68e4f27..42bf01ab6a8f 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -213,9 +213,17 @@ static int kvm_riscv_vcpu_set_reg_config(struct kvm_vcpu *vcpu,
 		}
 		break;
 	case KVM_REG_RISCV_CONFIG_REG(zicbom_block_size):
-		return -EOPNOTSUPP;
+		if (!riscv_isa_extension_available(vcpu->arch.isa, ZICBOM))
+			return -ENOENT;
+		if (reg_val != riscv_cbom_block_size)
+			return -EINVAL;
+		break;
 	case KVM_REG_RISCV_CONFIG_REG(zicboz_block_size):
-		return -EOPNOTSUPP;
+		if (!riscv_isa_extension_available(vcpu->arch.isa, ZICBOZ))
+			return -ENOENT;
+		if (reg_val != riscv_cboz_block_size)
+			return -EINVAL;
+		break;
 	case KVM_REG_RISCV_CONFIG_REG(mvendorid):
 		if (!vcpu->arch.ran_atleast_once)
 			vcpu->arch.mvendorid = reg_val;
-- 
2.41.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 4/6] RISC-V: KVM: do not EOPNOTSUPP in set KVM_REG_RISCV_TIMER_REG
  2023-07-31 12:04 ` Daniel Henrique Barboza
@ 2023-07-31 12:04   ` Daniel Henrique Barboza
  -1 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

The KVM_REG_RISCV_TIMER_REG can be read via get_one_reg(). But trying to
write anything in this reg via set_one_reg() results in an EOPNOTSUPP.

Change the API to behave like cbom_block_size: instead of always
erroring out with EOPNOTSUPP, allow userspace to write the same value
(riscv_timebase) back, throwing an EINVAL if a different value is
attempted.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 arch/riscv/kvm/vcpu_timer.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/kvm/vcpu_timer.c b/arch/riscv/kvm/vcpu_timer.c
index 527d269cafff..75486b25ac45 100644
--- a/arch/riscv/kvm/vcpu_timer.c
+++ b/arch/riscv/kvm/vcpu_timer.c
@@ -218,7 +218,8 @@ int kvm_riscv_vcpu_set_reg_timer(struct kvm_vcpu *vcpu,
 
 	switch (reg_num) {
 	case KVM_REG_RISCV_TIMER_REG(frequency):
-		ret = -EOPNOTSUPP;
+		if (reg_val != riscv_timebase)
+			return -EINVAL;
 		break;
 	case KVM_REG_RISCV_TIMER_REG(time):
 		gt->time_delta = reg_val - get_cycles64();
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 4/6] RISC-V: KVM: do not EOPNOTSUPP in set KVM_REG_RISCV_TIMER_REG
@ 2023-07-31 12:04   ` Daniel Henrique Barboza
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

The KVM_REG_RISCV_TIMER_REG can be read via get_one_reg(). But trying to
write anything in this reg via set_one_reg() results in an EOPNOTSUPP.

Change the API to behave like cbom_block_size: instead of always
erroring out with EOPNOTSUPP, allow userspace to write the same value
(riscv_timebase) back, throwing an EINVAL if a different value is
attempted.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 arch/riscv/kvm/vcpu_timer.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/kvm/vcpu_timer.c b/arch/riscv/kvm/vcpu_timer.c
index 527d269cafff..75486b25ac45 100644
--- a/arch/riscv/kvm/vcpu_timer.c
+++ b/arch/riscv/kvm/vcpu_timer.c
@@ -218,7 +218,8 @@ int kvm_riscv_vcpu_set_reg_timer(struct kvm_vcpu *vcpu,
 
 	switch (reg_num) {
 	case KVM_REG_RISCV_TIMER_REG(frequency):
-		ret = -EOPNOTSUPP;
+		if (reg_val != riscv_timebase)
+			return -EINVAL;
 		break;
 	case KVM_REG_RISCV_TIMER_REG(time):
 		gt->time_delta = reg_val - get_cycles64();
-- 
2.41.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 5/6] RISC-V: KVM: use EBUSY when !vcpu->arch.ran_atleast_once
  2023-07-31 12:04 ` Daniel Henrique Barboza
@ 2023-07-31 12:04   ` Daniel Henrique Barboza
  -1 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

vcpu_set_reg_config() and vcpu_set_reg_isa_ext() is throwing an
EOPNOTSUPP error when !vcpu->arch.ran_atleast_once. In similar cases
we're throwing an EBUSY error, like in mvendorid/marchid/mimpid
set_reg().

EOPNOTSUPP has a conotation of finality. EBUSY is more adequate in this
case since its a condition/error related to the vcpu lifecycle.

Change these EOPNOTSUPP instances to EBUSY.

Suggested-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 arch/riscv/kvm/vcpu_onereg.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index 42bf01ab6a8f..07ce747620f9 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -209,7 +209,7 @@ static int kvm_riscv_vcpu_set_reg_config(struct kvm_vcpu *vcpu,
 			vcpu->arch.isa[0] = reg_val;
 			kvm_riscv_vcpu_fp_reset(vcpu);
 		} else {
-			return -EOPNOTSUPP;
+			return -EBUSY;
 		}
 		break;
 	case KVM_REG_RISCV_CONFIG_REG(zicbom_block_size):
@@ -477,7 +477,7 @@ static int riscv_vcpu_set_isa_ext_single(struct kvm_vcpu *vcpu,
 			return -EINVAL;
 		kvm_riscv_vcpu_fp_reset(vcpu);
 	} else {
-		return -EOPNOTSUPP;
+		return -EBUSY;
 	}
 
 	return 0;
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 5/6] RISC-V: KVM: use EBUSY when !vcpu->arch.ran_atleast_once
@ 2023-07-31 12:04   ` Daniel Henrique Barboza
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

vcpu_set_reg_config() and vcpu_set_reg_isa_ext() is throwing an
EOPNOTSUPP error when !vcpu->arch.ran_atleast_once. In similar cases
we're throwing an EBUSY error, like in mvendorid/marchid/mimpid
set_reg().

EOPNOTSUPP has a conotation of finality. EBUSY is more adequate in this
case since its a condition/error related to the vcpu lifecycle.

Change these EOPNOTSUPP instances to EBUSY.

Suggested-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 arch/riscv/kvm/vcpu_onereg.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index 42bf01ab6a8f..07ce747620f9 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -209,7 +209,7 @@ static int kvm_riscv_vcpu_set_reg_config(struct kvm_vcpu *vcpu,
 			vcpu->arch.isa[0] = reg_val;
 			kvm_riscv_vcpu_fp_reset(vcpu);
 		} else {
-			return -EOPNOTSUPP;
+			return -EBUSY;
 		}
 		break;
 	case KVM_REG_RISCV_CONFIG_REG(zicbom_block_size):
@@ -477,7 +477,7 @@ static int riscv_vcpu_set_isa_ext_single(struct kvm_vcpu *vcpu,
 			return -EINVAL;
 		kvm_riscv_vcpu_fp_reset(vcpu);
 	} else {
-		return -EOPNOTSUPP;
+		return -EBUSY;
 	}
 
 	return 0;
-- 
2.41.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 6/6] docs: kvm: riscv: document EBUSY in KVM_SET_ONE_REG
  2023-07-31 12:04 ` Daniel Henrique Barboza
@ 2023-07-31 12:04   ` Daniel Henrique Barboza
  -1 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

The EBUSY errno is being used for KVM_SET_ONE_REG as a way to tell
userspace that a given reg can't be written after the vcpu started.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 Documentation/virt/kvm/api.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index c0ddd3035462..229e7cc091c8 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -2259,6 +2259,8 @@ Errors:
   EINVAL   invalid register ID, or no such register or used with VMs in
            protected virtualization mode on s390
   EPERM    (arm64) register access not allowed before vcpu finalization
+  EBUSY    (riscv) register access not allowed after the vcpu has run
+           at least once
   ======   ============================================================
 
 (These error codes are indicative only: do not rely on a specific error
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 6/6] docs: kvm: riscv: document EBUSY in KVM_SET_ONE_REG
@ 2023-07-31 12:04   ` Daniel Henrique Barboza
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-07-31 12:04 UTC (permalink / raw)
  To: kvm-riscv, linux-riscv, kvm; +Cc: anup, atishp, ajones, Daniel Henrique Barboza

The EBUSY errno is being used for KVM_SET_ONE_REG as a way to tell
userspace that a given reg can't be written after the vcpu started.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 Documentation/virt/kvm/api.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index c0ddd3035462..229e7cc091c8 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -2259,6 +2259,8 @@ Errors:
   EINVAL   invalid register ID, or no such register or used with VMs in
            protected virtualization mode on s390
   EPERM    (arm64) register access not allowed before vcpu finalization
+  EBUSY    (riscv) register access not allowed after the vcpu has run
+           at least once
   ======   ============================================================
 
 (These error codes are indicative only: do not rely on a specific error
-- 
2.41.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/6] RISC-V: KVM: change get_reg/set_reg error codes
  2023-07-31 12:04 ` Daniel Henrique Barboza
@ 2023-07-31 12:36   ` Andrew Jones
  -1 siblings, 0 replies; 26+ messages in thread
From: Andrew Jones @ 2023-07-31 12:36 UTC (permalink / raw)
  To: Daniel Henrique Barboza; +Cc: kvm-riscv, linux-riscv, kvm, anup, atishp

On Mon, Jul 31, 2023 at 09:04:14AM -0300, Daniel Henrique Barboza wrote:
> Hi,
> 
> This work was motivated by the changes made in QEMU in commit df817297d7
> ("target/riscv: update multi-letter extension KVM properties") where it
> was required to use EINVAL to try to assess whether a given extension is
> available in the host.
> 
> It turns out that the RISC-V KVM module makes regular use of the EIVAL
> error code in all kvm_get_one_reg() and kvm_set_one_reg() callbacks,
> which is not ideal. For example, ENOENT is a better error code for the
> case where a given register does not exist. While at it I decided to
> take a look at other error codes from these callbacks, comparing them
> with how other archs (ARM) handles the same error types, and changed
> some of the EOPNOTSUPP instances to either ENOENT or EBUSY.
> 
> I am aware that changing error codes can be problematic to existing
> userspaces. I took a look and no other major userspace (checked crosvm,
> rust-vmm, QEMU, kvmtool), aside from QEMU now checking for EIVAL (and we
> can't change that because of backwards compat for that particular case
> we're covering),

Merging this series just prior to some other API change, like adding
the get-reg-list ioctl[1], will allow QEMU to eventually drop the EINVAL
handling. This is because when QEMU sees the get-reg-list ioctl it will
know that get/set-reg-list has the updated API. At some point when QEMU
no longer wants to support a KVM which doesn't have get-reg-list, then
the EINVAL handling can be dropped.

And, once KVM has get-reg-list, then QEMU won't want to probe for
registers with get-one-reg anyway. Instead, it'll get the list once
and then check that each register it would have probed is in the list.

[1] https://lore.kernel.org/lkml/cover.1690273969.git.haibo1.xu@intel.com/T/


> will be impacted by this kind of change since they're
> all checking for "return < 0 then ..." instead of doing specific error
> handling based on the error value. This means that we're still in good
> time to make this kind of change while we're still in the initial steps
> of the RISC-V KVM ecossystem support.
> 
> Patch 3 happens to also change the behavior of the set_reg() for
> zicbom/zicboz block sizes. Instead of always erroring out we'll check if
> userspace is writing the same value that the host uses. In this case,
> allow the write to succeed (i.e. do nothing). This avoids the situation
> in which userspace reads cbom_block_size, find out that it's set to X,
> and then can't write the same value back to the register. It's a QOL
> improvement to allow userspace to be lazier when reading/writing regs.

Being able to write back the same value will greatly simplify
save/restore for QEMU, particularly when get-reg-list is available. QEMU
would then get the list of registers and, for save, it'll iterate the list
blindly, calling get-one-reg on each, storing each value. Then, for
restore, it'll blindly iterate again, writing each saved value back with
set-one-reg.

Thanks,
drew


> A
> similar change was also made in patch 4.
> 
> Patches are based on top of riscv_kvm_queue.
> 
> Daniel Henrique Barboza (6):
>   RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
>   RISC-V: KVM: use ENOENT in *_one_reg() when extension is unavailable
>   RISC-V: KVM: do not EOPNOTSUPP in set_one_reg() zicbo(m|z)
>   RISC-V: KVM: do not EOPNOTSUPP in set KVM_REG_RISCV_TIMER_REG
>   RISC-V: KVM: use EBUSY when !vcpu->arch.ran_atleast_once
>   docs: kvm: riscv: document EBUSY in KVM_SET_ONE_REG
> 
>  Documentation/virt/kvm/api.rst |  2 ++
>  arch/riscv/kvm/aia.c           |  4 +--
>  arch/riscv/kvm/vcpu_fp.c       | 12 ++++----
>  arch/riscv/kvm/vcpu_onereg.c   | 52 ++++++++++++++++++++--------------
>  arch/riscv/kvm/vcpu_sbi.c      | 16 ++++++-----
>  arch/riscv/kvm/vcpu_timer.c    | 11 +++----
>  6 files changed, 55 insertions(+), 42 deletions(-)
> 
> -- 
> 2.41.0
> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/6] RISC-V: KVM: change get_reg/set_reg error codes
@ 2023-07-31 12:36   ` Andrew Jones
  0 siblings, 0 replies; 26+ messages in thread
From: Andrew Jones @ 2023-07-31 12:36 UTC (permalink / raw)
  To: Daniel Henrique Barboza; +Cc: kvm-riscv, linux-riscv, kvm, anup, atishp

On Mon, Jul 31, 2023 at 09:04:14AM -0300, Daniel Henrique Barboza wrote:
> Hi,
> 
> This work was motivated by the changes made in QEMU in commit df817297d7
> ("target/riscv: update multi-letter extension KVM properties") where it
> was required to use EINVAL to try to assess whether a given extension is
> available in the host.
> 
> It turns out that the RISC-V KVM module makes regular use of the EIVAL
> error code in all kvm_get_one_reg() and kvm_set_one_reg() callbacks,
> which is not ideal. For example, ENOENT is a better error code for the
> case where a given register does not exist. While at it I decided to
> take a look at other error codes from these callbacks, comparing them
> with how other archs (ARM) handles the same error types, and changed
> some of the EOPNOTSUPP instances to either ENOENT or EBUSY.
> 
> I am aware that changing error codes can be problematic to existing
> userspaces. I took a look and no other major userspace (checked crosvm,
> rust-vmm, QEMU, kvmtool), aside from QEMU now checking for EIVAL (and we
> can't change that because of backwards compat for that particular case
> we're covering),

Merging this series just prior to some other API change, like adding
the get-reg-list ioctl[1], will allow QEMU to eventually drop the EINVAL
handling. This is because when QEMU sees the get-reg-list ioctl it will
know that get/set-reg-list has the updated API. At some point when QEMU
no longer wants to support a KVM which doesn't have get-reg-list, then
the EINVAL handling can be dropped.

And, once KVM has get-reg-list, then QEMU won't want to probe for
registers with get-one-reg anyway. Instead, it'll get the list once
and then check that each register it would have probed is in the list.

[1] https://lore.kernel.org/lkml/cover.1690273969.git.haibo1.xu@intel.com/T/


> will be impacted by this kind of change since they're
> all checking for "return < 0 then ..." instead of doing specific error
> handling based on the error value. This means that we're still in good
> time to make this kind of change while we're still in the initial steps
> of the RISC-V KVM ecossystem support.
> 
> Patch 3 happens to also change the behavior of the set_reg() for
> zicbom/zicboz block sizes. Instead of always erroring out we'll check if
> userspace is writing the same value that the host uses. In this case,
> allow the write to succeed (i.e. do nothing). This avoids the situation
> in which userspace reads cbom_block_size, find out that it's set to X,
> and then can't write the same value back to the register. It's a QOL
> improvement to allow userspace to be lazier when reading/writing regs.

Being able to write back the same value will greatly simplify
save/restore for QEMU, particularly when get-reg-list is available. QEMU
would then get the list of registers and, for save, it'll iterate the list
blindly, calling get-one-reg on each, storing each value. Then, for
restore, it'll blindly iterate again, writing each saved value back with
set-one-reg.

Thanks,
drew


> A
> similar change was also made in patch 4.
> 
> Patches are based on top of riscv_kvm_queue.
> 
> Daniel Henrique Barboza (6):
>   RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
>   RISC-V: KVM: use ENOENT in *_one_reg() when extension is unavailable
>   RISC-V: KVM: do not EOPNOTSUPP in set_one_reg() zicbo(m|z)
>   RISC-V: KVM: do not EOPNOTSUPP in set KVM_REG_RISCV_TIMER_REG
>   RISC-V: KVM: use EBUSY when !vcpu->arch.ran_atleast_once
>   docs: kvm: riscv: document EBUSY in KVM_SET_ONE_REG
> 
>  Documentation/virt/kvm/api.rst |  2 ++
>  arch/riscv/kvm/aia.c           |  4 +--
>  arch/riscv/kvm/vcpu_fp.c       | 12 ++++----
>  arch/riscv/kvm/vcpu_onereg.c   | 52 ++++++++++++++++++++--------------
>  arch/riscv/kvm/vcpu_sbi.c      | 16 ++++++-----
>  arch/riscv/kvm/vcpu_timer.c    | 11 +++----
>  6 files changed, 55 insertions(+), 42 deletions(-)
> 
> -- 
> 2.41.0
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 5/6] RISC-V: KVM: use EBUSY when !vcpu->arch.ran_atleast_once
  2023-07-31 12:04   ` Daniel Henrique Barboza
@ 2023-07-31 12:57     ` Andrew Jones
  -1 siblings, 0 replies; 26+ messages in thread
From: Andrew Jones @ 2023-07-31 12:57 UTC (permalink / raw)
  To: Daniel Henrique Barboza; +Cc: kvm-riscv, linux-riscv, kvm, anup, atishp

On Mon, Jul 31, 2023 at 09:04:19AM -0300, Daniel Henrique Barboza wrote:
> vcpu_set_reg_config() and vcpu_set_reg_isa_ext() is throwing an
> EOPNOTSUPP error when !vcpu->arch.ran_atleast_once. In similar cases
> we're throwing an EBUSY error, like in mvendorid/marchid/mimpid
> set_reg().
> 
> EOPNOTSUPP has a conotation of finality. EBUSY is more adequate in this
> case since its a condition/error related to the vcpu lifecycle.
> 
> Change these EOPNOTSUPP instances to EBUSY.
> 
> Suggested-by: Andrew Jones <ajones@ventanamicro.com>
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  arch/riscv/kvm/vcpu_onereg.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
> index 42bf01ab6a8f..07ce747620f9 100644
> --- a/arch/riscv/kvm/vcpu_onereg.c
> +++ b/arch/riscv/kvm/vcpu_onereg.c
> @@ -209,7 +209,7 @@ static int kvm_riscv_vcpu_set_reg_config(struct kvm_vcpu *vcpu,
>  			vcpu->arch.isa[0] = reg_val;
>  			kvm_riscv_vcpu_fp_reset(vcpu);
>  		} else {
> -			return -EOPNOTSUPP;
> +			return -EBUSY;
>  		}
>  		break;
>  	case KVM_REG_RISCV_CONFIG_REG(zicbom_block_size):
> @@ -477,7 +477,7 @@ static int riscv_vcpu_set_isa_ext_single(struct kvm_vcpu *vcpu,
>  			return -EINVAL;
>  		kvm_riscv_vcpu_fp_reset(vcpu);
>  	} else {
> -		return -EOPNOTSUPP;
> +		return -EBUSY;
>  	}

I think we should allow these ran_atleast_once type of registers to be
written when the value matches, as we now do for the other registers.
EBUSY should still be returned when the value doesn't match, though.

Thanks,
drew

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 5/6] RISC-V: KVM: use EBUSY when !vcpu->arch.ran_atleast_once
@ 2023-07-31 12:57     ` Andrew Jones
  0 siblings, 0 replies; 26+ messages in thread
From: Andrew Jones @ 2023-07-31 12:57 UTC (permalink / raw)
  To: Daniel Henrique Barboza; +Cc: kvm-riscv, linux-riscv, kvm, anup, atishp

On Mon, Jul 31, 2023 at 09:04:19AM -0300, Daniel Henrique Barboza wrote:
> vcpu_set_reg_config() and vcpu_set_reg_isa_ext() is throwing an
> EOPNOTSUPP error when !vcpu->arch.ran_atleast_once. In similar cases
> we're throwing an EBUSY error, like in mvendorid/marchid/mimpid
> set_reg().
> 
> EOPNOTSUPP has a conotation of finality. EBUSY is more adequate in this
> case since its a condition/error related to the vcpu lifecycle.
> 
> Change these EOPNOTSUPP instances to EBUSY.
> 
> Suggested-by: Andrew Jones <ajones@ventanamicro.com>
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
> ---
>  arch/riscv/kvm/vcpu_onereg.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
> index 42bf01ab6a8f..07ce747620f9 100644
> --- a/arch/riscv/kvm/vcpu_onereg.c
> +++ b/arch/riscv/kvm/vcpu_onereg.c
> @@ -209,7 +209,7 @@ static int kvm_riscv_vcpu_set_reg_config(struct kvm_vcpu *vcpu,
>  			vcpu->arch.isa[0] = reg_val;
>  			kvm_riscv_vcpu_fp_reset(vcpu);
>  		} else {
> -			return -EOPNOTSUPP;
> +			return -EBUSY;
>  		}
>  		break;
>  	case KVM_REG_RISCV_CONFIG_REG(zicbom_block_size):
> @@ -477,7 +477,7 @@ static int riscv_vcpu_set_isa_ext_single(struct kvm_vcpu *vcpu,
>  			return -EINVAL;
>  		kvm_riscv_vcpu_fp_reset(vcpu);
>  	} else {
> -		return -EOPNOTSUPP;
> +		return -EBUSY;
>  	}

I think we should allow these ran_atleast_once type of registers to be
written when the value matches, as we now do for the other registers.
EBUSY should still be returned when the value doesn't match, though.

Thanks,
drew

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/6] RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
  2023-07-31 12:04   ` Daniel Henrique Barboza
@ 2023-11-09  9:37     ` Andreas Schwab
  -1 siblings, 0 replies; 26+ messages in thread
From: Andreas Schwab @ 2023-11-09  9:37 UTC (permalink / raw)
  To: Daniel Henrique Barboza; +Cc: kvm-riscv, linux-riscv, kvm, anup, atishp, ajones

On Jul 31 2023, Daniel Henrique Barboza wrote:

> Existing userspaces can be affected by this error code change. We
> checked a few. As of current upstream code, crosvm doesn't check for any
> particular errno code when using kvm_(get|set)_one_reg(). Neither does
> QEMU.

That may break qemu:

$ qemu-system-riscv64 -cpu rv64 -machine virt,accel=kvm      
qemu-system-riscv64: Unable to read ISA_EXT KVM register ssaia, error -1

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/6] RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
@ 2023-11-09  9:37     ` Andreas Schwab
  0 siblings, 0 replies; 26+ messages in thread
From: Andreas Schwab @ 2023-11-09  9:37 UTC (permalink / raw)
  To: Daniel Henrique Barboza; +Cc: kvm-riscv, linux-riscv, kvm, anup, atishp, ajones

On Jul 31 2023, Daniel Henrique Barboza wrote:

> Existing userspaces can be affected by this error code change. We
> checked a few. As of current upstream code, crosvm doesn't check for any
> particular errno code when using kvm_(get|set)_one_reg(). Neither does
> QEMU.

That may break qemu:

$ qemu-system-riscv64 -cpu rv64 -machine virt,accel=kvm      
qemu-system-riscv64: Unable to read ISA_EXT KVM register ssaia, error -1

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/6] RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
  2023-11-09  9:37     ` Andreas Schwab
@ 2023-11-09 19:33       ` Daniel Henrique Barboza
  -1 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-09 19:33 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: kvm-riscv, linux-riscv, kvm, anup, atishp, ajones



On 11/9/23 06:37, Andreas Schwab wrote:
> On Jul 31 2023, Daniel Henrique Barboza wrote:
> 
>> Existing userspaces can be affected by this error code change. We
>> checked a few. As of current upstream code, crosvm doesn't check for any
>> particular errno code when using kvm_(get|set)_one_reg(). Neither does
>> QEMU.
> 
> That may break qemu:
> 
> $ qemu-system-riscv64 -cpu rv64 -machine virt,accel=kvm
> qemu-system-riscv64: Unable to read ISA_EXT KVM register ssaia, error -1

Which QEMU version are you using? This is a problem that was fixed upstream by:


commit 608bdebb6075b757e5505f6bbc60c45a54a1390b
Author: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Date:   Tue Oct 3 10:21:48 2023 -0300

     target/riscv/kvm: support KVM_GET_REG_LIST


If you're getting this error with upstream QEMU let me know and I'll take a look
there.


Thanks,


Daniel


> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/6] RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
@ 2023-11-09 19:33       ` Daniel Henrique Barboza
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-09 19:33 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: kvm-riscv, linux-riscv, kvm, anup, atishp, ajones



On 11/9/23 06:37, Andreas Schwab wrote:
> On Jul 31 2023, Daniel Henrique Barboza wrote:
> 
>> Existing userspaces can be affected by this error code change. We
>> checked a few. As of current upstream code, crosvm doesn't check for any
>> particular errno code when using kvm_(get|set)_one_reg(). Neither does
>> QEMU.
> 
> That may break qemu:
> 
> $ qemu-system-riscv64 -cpu rv64 -machine virt,accel=kvm
> qemu-system-riscv64: Unable to read ISA_EXT KVM register ssaia, error -1

Which QEMU version are you using? This is a problem that was fixed upstream by:


commit 608bdebb6075b757e5505f6bbc60c45a54a1390b
Author: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Date:   Tue Oct 3 10:21:48 2023 -0300

     target/riscv/kvm: support KVM_GET_REG_LIST


If you're getting this error with upstream QEMU let me know and I'll take a look
there.


Thanks,


Daniel


> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/6] RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
  2023-11-09 19:33       ` Daniel Henrique Barboza
@ 2023-11-13  8:30         ` Andreas Schwab
  -1 siblings, 0 replies; 26+ messages in thread
From: Andreas Schwab @ 2023-11-13  8:30 UTC (permalink / raw)
  To: Daniel Henrique Barboza; +Cc: kvm-riscv, linux-riscv, kvm, anup, atishp, ajones

On Nov 09 2023, Daniel Henrique Barboza wrote:

> Which QEMU version are you using?

The very latest release, both host and guest.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/6] RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
@ 2023-11-13  8:30         ` Andreas Schwab
  0 siblings, 0 replies; 26+ messages in thread
From: Andreas Schwab @ 2023-11-13  8:30 UTC (permalink / raw)
  To: Daniel Henrique Barboza; +Cc: kvm-riscv, linux-riscv, kvm, anup, atishp, ajones

On Nov 09 2023, Daniel Henrique Barboza wrote:

> Which QEMU version are you using?

The very latest release, both host and guest.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/6] RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
  2023-11-13  8:30         ` Andreas Schwab
@ 2023-11-13 10:27           ` Daniel Henrique Barboza
  -1 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-13 10:27 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: kvm-riscv, linux-riscv, kvm, anup, atishp, ajones



On 11/13/23 05:30, Andreas Schwab wrote:
> On Nov 09 2023, Daniel Henrique Barboza wrote:
> 
>> Which QEMU version are you using?
> 
> The very latest release, both host and guest.

If by "latest release" you mean kernel 6.6 and QEMU 8.1, this combination is
broken ATM.

Back in 8.1 QEMU was checking for EINVAL to make an educated guess of whether an
extension was unavailable but the register exists, versus if the register was alien
to KVM at all (qemu commit f7a69fa6e6). This turned out to be a mistake because
EINVAL was being thrown for all sorts of errors, and QEMU would be wiser to just
error out in all errors like other VMMs were doing (including kvmtool).

These were considerations made when proposing this KVM side change in the cover letter.
Other VMMs would be unaffected by it, and QEMU would need changes to adapt to the new
error codes. QEMU 8.2 is already adapted. It's not ideal, but it's better to take
a hit now while the RISC-V ecosystem is still new and make things tidy for the
future.

And now that I'm thinking more about it, I'll push a QEMU change in 8.1-stable to
alleviate the issue for 8.1. My apologies, I should've thought about it earlier ...


Thanks,

Daniel


> 

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/6] RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown
@ 2023-11-13 10:27           ` Daniel Henrique Barboza
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Henrique Barboza @ 2023-11-13 10:27 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: kvm-riscv, linux-riscv, kvm, anup, atishp, ajones



On 11/13/23 05:30, Andreas Schwab wrote:
> On Nov 09 2023, Daniel Henrique Barboza wrote:
> 
>> Which QEMU version are you using?
> 
> The very latest release, both host and guest.

If by "latest release" you mean kernel 6.6 and QEMU 8.1, this combination is
broken ATM.

Back in 8.1 QEMU was checking for EINVAL to make an educated guess of whether an
extension was unavailable but the register exists, versus if the register was alien
to KVM at all (qemu commit f7a69fa6e6). This turned out to be a mistake because
EINVAL was being thrown for all sorts of errors, and QEMU would be wiser to just
error out in all errors like other VMMs were doing (including kvmtool).

These were considerations made when proposing this KVM side change in the cover letter.
Other VMMs would be unaffected by it, and QEMU would need changes to adapt to the new
error codes. QEMU 8.2 is already adapted. It's not ideal, but it's better to take
a hit now while the RISC-V ecosystem is still new and make things tidy for the
future.

And now that I'm thinking more about it, I'll push a QEMU change in 8.1-stable to
alleviate the issue for 8.1. My apologies, I should've thought about it earlier ...


Thanks,

Daniel


> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2023-11-13 10:27 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-31 12:04 [PATCH 0/6] RISC-V: KVM: change get_reg/set_reg error codes Daniel Henrique Barboza
2023-07-31 12:04 ` Daniel Henrique Barboza
2023-07-31 12:04 ` [PATCH 1/6] RISC-V: KVM: return ENOENT in *_one_reg() when reg is unknown Daniel Henrique Barboza
2023-07-31 12:04   ` Daniel Henrique Barboza
2023-11-09  9:37   ` Andreas Schwab
2023-11-09  9:37     ` Andreas Schwab
2023-11-09 19:33     ` Daniel Henrique Barboza
2023-11-09 19:33       ` Daniel Henrique Barboza
2023-11-13  8:30       ` Andreas Schwab
2023-11-13  8:30         ` Andreas Schwab
2023-11-13 10:27         ` Daniel Henrique Barboza
2023-11-13 10:27           ` Daniel Henrique Barboza
2023-07-31 12:04 ` [PATCH 2/6] RISC-V: KVM: use ENOENT in *_one_reg() when extension is unavailable Daniel Henrique Barboza
2023-07-31 12:04   ` Daniel Henrique Barboza
2023-07-31 12:04 ` [PATCH 3/6] RISC-V: KVM: do not EOPNOTSUPP in set_one_reg() zicbo(m|z) Daniel Henrique Barboza
2023-07-31 12:04   ` Daniel Henrique Barboza
2023-07-31 12:04 ` [PATCH 4/6] RISC-V: KVM: do not EOPNOTSUPP in set KVM_REG_RISCV_TIMER_REG Daniel Henrique Barboza
2023-07-31 12:04   ` Daniel Henrique Barboza
2023-07-31 12:04 ` [PATCH 5/6] RISC-V: KVM: use EBUSY when !vcpu->arch.ran_atleast_once Daniel Henrique Barboza
2023-07-31 12:04   ` Daniel Henrique Barboza
2023-07-31 12:57   ` Andrew Jones
2023-07-31 12:57     ` Andrew Jones
2023-07-31 12:04 ` [PATCH 6/6] docs: kvm: riscv: document EBUSY in KVM_SET_ONE_REG Daniel Henrique Barboza
2023-07-31 12:04   ` Daniel Henrique Barboza
2023-07-31 12:36 ` [PATCH 0/6] RISC-V: KVM: change get_reg/set_reg error codes Andrew Jones
2023-07-31 12:36   ` Andrew Jones

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.