Re: [PATCH kvmtool] arm64: pvtime: Use correct region size

2022-06-29 Thread Andre Przywara
On Wed, 29 Jun 2022 11:39:05 +0100
Alexandru Elisei  wrote:

Hi,

> pvtime uses ARM_PVTIME_BASE instead of ARM_PVTIME_SIZE for the size of the
> memory region given to the guest, which causes to the following error when
> creating a flash device (via the -F/--flash command line argument):
> 
>   Error: RAM (read-only) region [200-27f] would overlap RAM region 
> [102-203]
> 
> The read-only region represents the guest memory where the flash image is
> copied by kvmtool. The region starting at 0x102_ (ARM_PVTIME_BASE) is
> the pvtime region, which should be 64K in size. kvmtool erroneously creates
> the region to be ARM_PVTIME_BASE in size instead, and the last address
> becomes:
> 
> ARM_PVTIME_BASE + ARM_PVTIME_BASE - 1 = 0x102_ + 0x102_ - 1 = 
> 0x203_
> 
> which corresponds to the end of the region from the error message.
> 
> Do the right thing and make the pvtime memory region ARM_PVTIME_SIZE = 64K
> bytes, as it was intended.
> 
> Fixes: 7d4671e5d372 ("aarch64: Add stolen time support")
> Reported-by: Pierre Gondois 
> Signed-off-by: Alexandru Elisei 

Oops, this looks indeed like a glaring bug, PVTIME_SIZE was not used
anywhere.

Reviewed-by: Andre Przywara 

Cheers,
Andre

> ---
>  arm/aarch64/pvtime.c | 10 +-
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/arm/aarch64/pvtime.c b/arm/aarch64/pvtime.c
> index a49cf3ed5478..2933ac7ca959 100644
> --- a/arm/aarch64/pvtime.c
> +++ b/arm/aarch64/pvtime.c
> @@ -14,15 +14,15 @@ static int pvtime__alloc_region(struct kvm *kvm)
>   char *mem;
>   int ret = 0;
>  
> - mem = mmap(NULL, ARM_PVTIME_BASE, PROT_RW,
> + mem = mmap(NULL, ARM_PVTIME_SIZE, PROT_RW,
>  MAP_ANON_NORESERVE, -1, 0);
>   if (mem == MAP_FAILED)
>   return -errno;
>  
>   ret = kvm__register_ram(kvm, ARM_PVTIME_BASE,
> - ARM_PVTIME_BASE, mem);
> + ARM_PVTIME_SIZE, mem);
>   if (ret) {
> - munmap(mem, ARM_PVTIME_BASE);
> + munmap(mem, ARM_PVTIME_SIZE);
>   return ret;
>   }
>  
> @@ -36,8 +36,8 @@ static int pvtime__teardown_region(struct kvm *kvm)
>   return 0;
>  
>   kvm__destroy_mem(kvm, ARM_PVTIME_BASE,
> -  ARM_PVTIME_BASE, usr_mem);
> - munmap(usr_mem, ARM_PVTIME_BASE);
> +  ARM_PVTIME_SIZE, usr_mem);
> + munmap(usr_mem, ARM_PVTIME_SIZE);
>   usr_mem = NULL;
>   return 0;
>  }

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v4 kvmtool 08/12] builtin_run: Allow standard size specifiers for memory

2022-06-16 Thread Andre Przywara
On Thu, 16 Jun 2022 14:48:24 +0100
Alexandru Elisei  wrote:

> From: Suzuki K Poulose 
> 
> Allow the user to use the standard B (bytes), K (kilobytes), M (megabytes),
> G (gigabytes), T (terabytes) and P (petabytes) suffixes for memory size.
> When none are specified, the default is megabytes.
> 
> Also raise an error if the guest specifies 0 as the memory size, instead
> of treating it as uninitialized, as kvmtool has done so far.
> 
> Signed-off-by: Suzuki K Poulose 
> Signed-off-by: Alexandru Elisei 

Thanks, looks good now!

Reviewed-by: Andre Przywara 

Cheers,
Andre

> ---
>  builtin-run.c | 59 ++-
>  1 file changed, 54 insertions(+), 5 deletions(-)
> 
> diff --git a/builtin-run.c b/builtin-run.c
> index dcd08f739469..8b4e865f0a0e 100644
> --- a/builtin-run.c
> +++ b/builtin-run.c
> @@ -49,9 +49,11 @@
>  #include 
>  #include 
>  
> -#define MB_SHIFT (20)
>  #define KB_SHIFT (10)
> +#define MB_SHIFT (20)
>  #define GB_SHIFT (30)
> +#define TB_SHIFT (40)
> +#define PB_SHIFT (50)
>  
>  __thread struct kvm_cpu *current_kvm_cpu;
>  
> @@ -87,6 +89,54 @@ void kvm_run_set_wrapper_sandbox(void)
>   kvm_run_wrapper = KVM_RUN_SANDBOX;
>  }
>  
> +static int parse_mem_unit(char **next)
> +{
> + switch (**next) {
> + case 'B': case 'b': (*next)++; return 0;
> + case 'K': case 'k': (*next)++; return KB_SHIFT;
> + case 'M': case 'm': (*next)++; return MB_SHIFT;
> + case 'G': case 'g': (*next)++; return GB_SHIFT;
> + case 'T': case 't': (*next)++; return TB_SHIFT;
> + case 'P': case 'p': (*next)++; return PB_SHIFT;
> + }
> +
> + return MB_SHIFT;
> +}
> +
> +static u64 parse_mem_option(const char *nptr, char **next)
> +{
> + u64 shift;
> + u64 val;
> +
> + errno = 0;
> + val = strtoull(nptr, next, 10);
> + if (errno == ERANGE)
> + die("Memory too large: %s", nptr);
> + if (*next == nptr)
> + die("Invalid memory specifier: %s", nptr);
> +
> + shift = parse_mem_unit(next);
> + if ((val << shift) < val)
> + die("Memory too large: %s", nptr);
> +
> + return val << shift;
> +}
> +
> +static int mem_parser(const struct option *opt, const char *arg, int unset)
> +{
> + struct kvm *kvm = opt->ptr;
> + char *next;
> +
> + kvm->cfg.ram_size = parse_mem_option(arg, );
> + if (kvm->cfg.ram_size == 0)
> + die("Invalid RAM size: %s", arg);
> +
> + if (*next != '\0')
> + die("Invalid memory specifier: %s", arg);
> +
> + return 0;
> +}
> +
>  #ifndef OPT_ARCH_RUN
>  #define OPT_ARCH_RUN(...)
>  #endif
> @@ -97,8 +147,9 @@ void kvm_run_set_wrapper_sandbox(void)
>   OPT_STRING('\0', "name", &(cfg)->guest_name, "guest name",  \
>   "A name for the guest"),\
>   OPT_INTEGER('c', "cpus", &(cfg)->nrcpus, "Number of CPUs"), \
> - OPT_U64('m', "mem", &(cfg)->ram_size, "Virtual machine memory"  \
> - " size in MB."),\
> + OPT_CALLBACK('m', "mem", NULL, "size[BKMGTP]",  \
> +  "Virtual machine memory size, by default measured" \
> +  " in megabytes (M)", mem_parser, kvm), \
>   OPT_CALLBACK('d', "disk", kvm, "image or rootfs_dir", "Disk "   \
>   " image or rootfs directory", img_name_parser,  \
>   kvm),   \
> @@ -522,8 +573,6 @@ static void kvm_run_validate_cfg(struct kvm *kvm)
>   pr_warning("Ignoring initrd file when loading a firmware 
> image");
>  
>   if (kvm->cfg.ram_size) {
> - /* User specifies RAM size in megabytes. */
> - kvm->cfg.ram_size <<= MB_SHIFT;
>   available_ram = host_ram_size();
>   if (available_ram && kvm->cfg.ram_size > available_ram) {
>   pr_warning("Guest memory size %lluMB exceeds host 
> physical RAM size %lluMB",

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v4 kvmtool 02/12] builtin-run: Always use RAM size in bytes

2022-06-16 Thread Andre Przywara
On Thu, 16 Jun 2022 14:48:18 +0100
Alexandru Elisei  wrote:

> The user can specify the virtual machine memory size in MB, which is saved
> in cfg->ram_size. kvmtool validates it against the host memory size,
> converted from bytes to MB. ram_size is then converted to bytes, and this
> is how it is used throughout the rest of kvmtool.
> 
> To avoid any confusion about the unit of measurement, especially once the
> user is allowed to specify the unit of measurement, always use ram_size in
> bytes.
> 
> Signed-off-by: Alexandru Elisei 

That looks good to me now, many thanks for the changes!
I ran a few large VMs (up to 1TB guest), also tested on an ARM32 host, it
all seems to still work fine, and no UBSAN messages.

Reviewed-by: Andre Przywara 

Cheers,
Andre


> ---
>  builtin-run.c| 19 ++-
>  include/kvm/kvm-config.h |  7 ---
>  include/kvm/kvm.h|  2 +-
>  3 files changed, 15 insertions(+), 13 deletions(-)
> 
> diff --git a/builtin-run.c b/builtin-run.c
> index 0126c9fbcba6..2bf93fe13c92 100644
> --- a/builtin-run.c
> +++ b/builtin-run.c
> @@ -36,6 +36,7 @@
>  
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  #include 
> @@ -264,7 +265,7 @@ static u64 host_ram_size(void)
>   return 0;
>   }
>  
> - return (nr_pages * page_size) >> MB_SHIFT;
> + return (u64)nr_pages * page_size;
>  }
>  
>  /*
> @@ -278,11 +279,11 @@ static u64 get_ram_size(int nr_cpus)
>   u64 available;
>   u64 ram_size;
>  
> - ram_size= 64 * (nr_cpus + 3);
> + ram_size= (u64)SZ_64M * (nr_cpus + 3);
>  
>   available   = host_ram_size() * RAM_SIZE_RATIO;
>   if (!available)
> - available = MIN_RAM_SIZE_MB;
> + available = MIN_RAM_SIZE;
>  
>   if (ram_size > available)
>   ram_size= available;
> @@ -595,13 +596,13 @@ static struct kvm *kvm_cmd_run_init(int argc, const 
> char **argv)
>  
>   if (!kvm->cfg.ram_size)
>   kvm->cfg.ram_size = get_ram_size(kvm->cfg.nrcpus);
> + else
> + kvm->cfg.ram_size <<= MB_SHIFT;
>  
>   if (kvm->cfg.ram_size > host_ram_size())
>   pr_warning("Guest memory size %lluMB exceeds host physical RAM 
> size %lluMB",
> - (unsigned long long)kvm->cfg.ram_size,
> - (unsigned long long)host_ram_size());
> -
> - kvm->cfg.ram_size <<= MB_SHIFT;
> + (unsigned long long)kvm->cfg.ram_size >> MB_SHIFT,
> + (unsigned long long)host_ram_size() >> MB_SHIFT);
>  
>   if (!kvm->cfg.dev)
>   kvm->cfg.dev = DEFAULT_KVM_DEV;
> @@ -676,12 +677,12 @@ static struct kvm *kvm_cmd_run_init(int argc, const 
> char **argv)
>   if (kvm->cfg.kernel_filename) {
>   printf("  # %s run -k %s -m %Lu -c %d --name %s\n", 
> KVM_BINARY_NAME,
>  kvm->cfg.kernel_filename,
> -(unsigned long long)kvm->cfg.ram_size / 1024 / 1024,
> +(unsigned long long)kvm->cfg.ram_size >> MB_SHIFT,
>  kvm->cfg.nrcpus, kvm->cfg.guest_name);
>   } else if (kvm->cfg.firmware_filename) {
>   printf("  # %s run --firmware %s -m %Lu -c %d --name %s\n", 
> KVM_BINARY_NAME,
>  kvm->cfg.firmware_filename,
> -(unsigned long long)kvm->cfg.ram_size / 1024 / 1024,
> +(unsigned long long)kvm->cfg.ram_size >> MB_SHIFT,
>  kvm->cfg.nrcpus, kvm->cfg.guest_name);
>   }
>  
> diff --git a/include/kvm/kvm-config.h b/include/kvm/kvm-config.h
> index 6a5720c4c7d4..31bc89520d52 100644
> --- a/include/kvm/kvm-config.h
> +++ b/include/kvm/kvm-config.h
> @@ -5,6 +5,8 @@
>  #include "kvm/vfio.h"
>  #include "kvm/kvm-config-arch.h"
>  
> +#include 
> +
>  #define DEFAULT_KVM_DEV  "/dev/kvm"
>  #define DEFAULT_CONSOLE  "serial"
>  #define DEFAULT_NETWORK  "user"
> @@ -15,14 +17,13 @@
>  #define DEFAULT_SCRIPT   "none"
>  #define DEFAULT_SANDBOX_FILENAME "guest/sandbox.sh"
>  
> -#define MIN_RAM_SIZE_MB  (64ULL)
> -#define MIN_RAM_SIZE_BYTE(MIN_RAM_SIZE_MB << MB_SHIFT)
> +#define MIN_RAM_SIZE SZ_64M
>  
>  struct kvm_config {
>   struct kvm_config_arch arch;
>   struct disk_image_params disk_image[MAX_DISK_IMAGES];
>   struct vf

Re: [PATCH v4 kvmtool 04/12] builtin-run: Add arch hook to validate VM configuration

2022-06-16 Thread Andre Przywara
On Thu, 16 Jun 2022 14:48:20 +0100
Alexandru Elisei  wrote:

> Architectures are free to set their own command line options. Add an
> architecture specific hook to validate these options.
> 
> For now, the hook does nothing, but it will be used in later patches.
> 
> Signed-off-by: Alexandru Elisei 

Reviewed-by: Andre Przywara 

Cheers,
Andre

> ---
>  Makefile  | 1 +
>  arm/aarch32/kvm.c | 5 +
>  arm/aarch64/kvm.c | 4 
>  builtin-run.c | 2 ++
>  include/kvm/kvm.h | 1 +
>  mips/kvm.c| 4 
>  powerpc/kvm.c | 4 
>  riscv/kvm.c   | 4 
>  x86/kvm.c | 4 
>  9 files changed, 29 insertions(+)
>  create mode 100644 arm/aarch32/kvm.c
> 
> diff --git a/Makefile b/Makefile
> index 6464446a9f24..64bb9c95b6f6 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -170,6 +170,7 @@ ifeq ($(ARCH), arm)
>   OBJS+= $(OBJS_ARM_COMMON)
>   OBJS+= arm/aarch32/arm-cpu.o
>   OBJS+= arm/aarch32/kvm-cpu.o
> + OBJS+= arm/aarch32/kvm.o
>   ARCH_INCLUDE:= $(HDRS_ARM_COMMON)
>   ARCH_INCLUDE+= -Iarm/aarch32/include
>   CFLAGS  += -march=armv7-a
> diff --git a/arm/aarch32/kvm.c b/arm/aarch32/kvm.c
> new file mode 100644
> index ..ae33ac92479a
> --- /dev/null
> +++ b/arm/aarch32/kvm.c
> @@ -0,0 +1,5 @@
> +#include "kvm/kvm.h"
> +
> +void kvm__arch_validate_cfg(struct kvm *kvm)
> +{
> +}
> diff --git a/arm/aarch64/kvm.c b/arm/aarch64/kvm.c
> index f3fe854e0b3f..ca348f118a56 100644
> --- a/arm/aarch64/kvm.c
> +++ b/arm/aarch64/kvm.c
> @@ -37,6 +37,10 @@ int vcpu_affinity_parser(const struct option *opt, const 
> char *arg, int unset)
>   return 0;
>  }
>  
> +void kvm__arch_validate_cfg(struct kvm *kvm)
> +{
> +}
> +
>  /*
>   * Return the TEXT_OFFSET value that the guest kernel expects. Note
>   * that pre-3.17 kernels expose this value using the native endianness
> diff --git a/builtin-run.c b/builtin-run.c
> index e1770b3c9df2..dcd08f739469 100644
> --- a/builtin-run.c
> +++ b/builtin-run.c
> @@ -531,6 +531,8 @@ static void kvm_run_validate_cfg(struct kvm *kvm)
>   (unsigned long long)available_ram >> MB_SHIFT);
>   }
>   }
> +
> + kvm__arch_validate_cfg(kvm);
>  }
>  
>  static struct kvm *kvm_cmd_run_init(int argc, const char **argv)
> diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
> index 7b14b33b50ca..9f7b2fb26e95 100644
> --- a/include/kvm/kvm.h
> +++ b/include/kvm/kvm.h
> @@ -187,6 +187,7 @@ int kvm__get_sock_by_instance(const char *name);
>  int kvm__enumerate_instances(int (*callback)(const char *name, int pid));
>  void kvm__remove_socket(const char *name);
>  
> +void kvm__arch_validate_cfg(struct kvm *kvm);
>  void kvm__arch_set_cmdline(char *cmdline, bool video);
>  void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 
> ram_size);
>  void kvm__arch_delete_ram(struct kvm *kvm);
> diff --git a/mips/kvm.c b/mips/kvm.c
> index e668cbbefb25..cebec5ae0178 100644
> --- a/mips/kvm.c
> +++ b/mips/kvm.c
> @@ -13,6 +13,10 @@ struct kvm_ext kvm_req_ext[] = {
>   { 0, 0 }
>  };
>  
> +void kvm__arch_validate_cfg(struct kvm *kvm)
> +{
> +}
> +
>  void kvm__arch_read_term(struct kvm *kvm)
>  {
>   virtio_console__inject_interrupt(kvm);
> diff --git a/powerpc/kvm.c b/powerpc/kvm.c
> index 702d67dca614..3215b579f5dc 100644
> --- a/powerpc/kvm.c
> +++ b/powerpc/kvm.c
> @@ -48,6 +48,10 @@ struct kvm_ext kvm_req_ext[] = {
>   { 0, 0 }
>  };
>  
> +void kvm__arch_validate_cfg(struct kvm *kvm)
> +{
> +}
> +
>  static uint32_t mfpvr(void)
>  {
>   uint32_t r;
> diff --git a/riscv/kvm.c b/riscv/kvm.c
> index 84e02779a91c..7fb496282f4c 100644
> --- a/riscv/kvm.c
> +++ b/riscv/kvm.c
> @@ -13,6 +13,10 @@ struct kvm_ext kvm_req_ext[] = {
>   { 0, 0 },
>  };
>  
> +void kvm__arch_validate_cfg(struct kvm *kvm)
> +{
> +}
> +
>  bool kvm__arch_cpu_supports_vm(void)
>  {
>   /* The KVM capability check is enough. */
> diff --git a/x86/kvm.c b/x86/kvm.c
> index 3e0f0b743f8c..6683a5c81d49 100644
> --- a/x86/kvm.c
> +++ b/x86/kvm.c
> @@ -35,6 +35,10 @@ struct kvm_ext kvm_req_ext[] = {
>   { 0, 0 }
>  };
>  
> +void kvm__arch_validate_cfg(struct kvm *kvm)
> +{
> +}
> +
>  bool kvm__arch_cpu_supports_vm(void)
>  {
>   struct cpuid_regs regs;

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool] arm: gic: fdt: fix PPI CPU mask calculation

2022-06-16 Thread Andre Przywara
The GICv2 DT binding describes the third cell in each interrupt
descriptor as holding the trigger type, but also the CPU mask that this
IRQ applies to, in bits [15:8]. However this is not the case for GICv3,
where we don't use a CPU mask in the third cell: a simple mask wouldn't
fit for the many more supported cores anyway.

At the moment we fill this CPU mask field regardless of the GIC type,
for the PMU and arch timer DT nodes. This is not only the wrong thing to
do in case of a GICv3, but also triggers UBSAN splats when using more
than 30 cores, as we do shifting beyond what a u32 can hold:
$ lkvm run -k Image -c 31 --pmu
arm/timer.c:13:22: runtime error: left shift of 1 by 31 places cannot be 
represented in type 'int'
arm/timer.c:13:38: runtime error: signed integer overflow: -2147483648 - 1 
cannot be represented in type 'int'
arm/timer.c:13:43: runtime error: left shift of 2147483647 by 8 places cannot 
be represented in type 'int'
arm/aarch64/pmu.c:202:22: runtime error: left shift of 1 by 31 places cannot be 
represented in type 'int'
arm/aarch64/pmu.c:202:38: runtime error: signed integer overflow: -2147483648 - 
1 cannot be represented in type 'int'
arm/aarch64/pmu.c:202:43: runtime error: left shift of 2147483647 by 8 places 
cannot be represented in type 'int'

Fix that by adding a function that creates the mask by looking at the
GIC type first, and returning zero when a GICv3 is used. Also we
explicitly check for the CPU limit again, even though this would be
done before already, when we try to create a GICv2 VM with more than 8
cores.

Signed-off-by: Andre Przywara 
---
 arm/aarch64/pmu.c|  3 +--
 arm/gic.c| 13 +
 arm/include/arm-common/gic.h |  1 +
 arm/timer.c  |  4 +---
 4 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/arm/aarch64/pmu.c b/arm/aarch64/pmu.c
index 5f189b32..5ed4979a 100644
--- a/arm/aarch64/pmu.c
+++ b/arm/aarch64/pmu.c
@@ -199,8 +199,7 @@ void pmu__generate_fdt_nodes(void *fdt, struct kvm *kvm)
int pmu_id = -ENXIO;
int i;
 
-   u32 cpu_mask = (((1 << kvm->nrcpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) \
-  & GIC_FDT_IRQ_PPI_CPU_MASK;
+   u32 cpu_mask = gic__get_fdt_irq_cpumask(kvm);
u32 irq_prop[] = {
cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
cpu_to_fdt32(irq - 16),
diff --git a/arm/gic.c b/arm/gic.c
index 26be4b4c..a223a72c 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -399,6 +399,19 @@ void gic__generate_fdt_nodes(void *fdt, enum irqchip_type 
type)
_FDT(fdt_end_node(fdt));
 }
 
+u32 gic__get_fdt_irq_cpumask(struct kvm *kvm)
+{
+   /* Only for GICv2 */
+   if (kvm->cfg.arch.irqchip == IRQCHIP_GICV3 ||
+   kvm->cfg.arch.irqchip == IRQCHIP_GICV3_ITS)
+   return 0;
+
+   if (kvm->nrcpus > 8)
+   return GIC_FDT_IRQ_PPI_CPU_MASK;
+
+   return ((1U << kvm->nrcpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT;
+}
+
 #define KVM_IRQCHIP_IRQ(x) (KVM_ARM_IRQ_TYPE_SPI << KVM_ARM_IRQ_TYPE_SHIFT) |\
   ((x) & KVM_ARM_IRQ_NUM_MASK)
 
diff --git a/arm/include/arm-common/gic.h b/arm/include/arm-common/gic.h
index ec9cf31a..ad8bcbf2 100644
--- a/arm/include/arm-common/gic.h
+++ b/arm/include/arm-common/gic.h
@@ -37,6 +37,7 @@ int gic__alloc_irqnum(void);
 int gic__create(struct kvm *kvm, enum irqchip_type type);
 int gic__create_gicv2m_frame(struct kvm *kvm, u64 msi_frame_addr);
 void gic__generate_fdt_nodes(void *fdt, enum irqchip_type type);
+u32 gic__get_fdt_irq_cpumask(struct kvm *kvm);
 
 int gic__add_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd,
   int resample_fd);
diff --git a/arm/timer.c b/arm/timer.c
index 71bfe8d4..6acc50ef 100644
--- a/arm/timer.c
+++ b/arm/timer.c
@@ -9,9 +9,7 @@
 void timer__generate_fdt_nodes(void *fdt, struct kvm *kvm, int *irqs)
 {
const char compatible[] = "arm,armv8-timer\0arm,armv7-timer";
-
-   u32 cpu_mask = (((1 << kvm->nrcpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) \
-  & GIC_FDT_IRQ_PPI_CPU_MASK;
+   u32 cpu_mask = gic__get_fdt_irq_cpumask(kvm);
u32 irq_prop[] = {
cpu_to_fdt32(GIC_FDT_IRQ_TYPE_PPI),
cpu_to_fdt32(irqs[0]),
-- 
2.25.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v3 kvmtool 09/13] builtin_run: Allow standard size specifiers for memory

2022-06-06 Thread Andre Przywara
On Wed, 1 Jun 2022 21:13:27 +0100
Alexandru Elisei  wrote:

Hi,

> On Wed, Jun 01, 2022 at 08:39:08PM +0100, Alexandru Elisei wrote:
> > Hi,
> > 
> > On Wed, Jun 01, 2022 at 05:14:00PM +0100, Andre Przywara wrote:  
> > > On Wed, 1 Jun 2022 15:17:50 +0100
> > > Alexandru Elisei  wrote:
> > > 
> > > Hi Alex,
> > >   
> > > > Hi,
> > > > 
> > > > Thank you for having a look! Replies below.
> > > > 
> > > > On Wed, Jun 01, 2022 at 02:39:55PM +0100, Andre Przywara wrote:  
> > > > > On Wed, 25 May 2022 12:23:41 +0100
> > > > > Alexandru Elisei  wrote:
> > > > > 
> > > > > Hi,
> > > > > 
> > > > > > From: Suzuki K Poulose 
> > > > > > 
> > > > > > Allow the user to use the standard B (bytes), K (kilobytes), M 
> > > > > > (megabytes),
> > > > > > G (gigabytes), T (terabytes) and P (petabytes) suffixes for memory 
> > > > > > size.
> > > > > > When none are specified, the default is megabytes.
> > > > > > 
> > > > > > Also raise an error if the guest specifies 0 as the memory size, 
> > > > > > instead
> > > > > > of treating it as uninitialized, as kvmtool has done so far.
> > > > > > 
> > > > > > Signed-off-by: Suzuki K Poulose 
> > > > > > Signed-off-by: Alexandru Elisei 
> > > > > > ---
> > > > > >  builtin-run.c | 65 
> > > > > > +++
> > > > > >  1 file changed, 60 insertions(+), 5 deletions(-)
> > > > > > 
> > > > > > diff --git a/builtin-run.c b/builtin-run.c
> > > > > > index 2ef159cdb2a3..a49698d5b2fe 100644
> > > > > > --- a/builtin-run.c
> > > > > > +++ b/builtin-run.c
> > > > > > @@ -49,9 +49,11 @@
> > > > > >  #include 
> > > > > >  #include 
> > > > > >  
> > > > > > -#define MB_SHIFT   (20)
> > > > > >  #define KB_SHIFT   (10)
> > > > > > +#define MB_SHIFT   (20)
> > > > > >  #define GB_SHIFT   (30)
> > > > > > +#define TB_SHIFT   (40)
> > > > > > +#define PB_SHIFT   (50)
> > > > > 
> > > > > Can we lose the parentheses?
> > > > 
> > > > Yes.
> > > >   
> > > > > 
> > > > > >  
> > > > > >  __thread struct kvm_cpu *current_kvm_cpu;
> > > > > >  
> > > > > > @@ -87,6 +89,60 @@ void kvm_run_set_wrapper_sandbox(void)
> > > > > > kvm_run_wrapper = KVM_RUN_SANDBOX;
> > > > > >  }
> > > > > >  
> > > > > > +static int parse_mem_unit(char **next)
> > > > > > +{
> > > > > > +   int shift = -1;
> > > > > > +
> > > > > > +   switch (**next) {
> > > > > > +   case 'B': case 'b': shift = 0; break;
> > > > > > +   case 'K': case 'k': shift = KB_SHIFT; break;
> > > > > > +   case 'M': case 'm': shift = MB_SHIFT; break;
> > > > > > +   case 'G': case 'g': shift = GB_SHIFT; break;
> > > > > > +   case 'T': case 't': shift = TB_SHIFT; break;
> > > > > > +   case 'P': case 'p': shift = PB_SHIFT; break;
> > > > > > +   }
> > > > > > +
> > > > > > +   if (shift == -1) {
> > > > > > +   /* The default is megabytes. */
> > > > > > +   shift = MB_SHIFT;
> > > > > 
> > > > > Doesn't that look better inside the switch/case?
> > > > >   default: return MB_SHIFT;
> > > > 
> > > > I think that change alone breaks the logic.
> > > > 
> > > > The code needs to advance next if and only if it matches on one of the
> > > > characters. I'll have a go at advancing next in each of the switch arms
> > > > above (with the exception of the default one, which I'll add) to see 
> > > > how it
> > > > ends up looking.  
> > > 
> > > Mmh, but I meant:
> > > {
> > >   switch (**next) {
> > >   case 'B': case 'b': shift = 0; break;
> > 

Re: [PATCH v3 kvmtool 09/13] builtin_run: Allow standard size specifiers for memory

2022-06-01 Thread Andre Przywara
On Wed, 1 Jun 2022 15:17:50 +0100
Alexandru Elisei  wrote:

Hi Alex,

> Hi,
> 
> Thank you for having a look! Replies below.
> 
> On Wed, Jun 01, 2022 at 02:39:55PM +0100, Andre Przywara wrote:
> > On Wed, 25 May 2022 12:23:41 +0100
> > Alexandru Elisei  wrote:
> > 
> > Hi,
> >   
> > > From: Suzuki K Poulose 
> > > 
> > > Allow the user to use the standard B (bytes), K (kilobytes), M 
> > > (megabytes),
> > > G (gigabytes), T (terabytes) and P (petabytes) suffixes for memory size.
> > > When none are specified, the default is megabytes.
> > > 
> > > Also raise an error if the guest specifies 0 as the memory size, instead
> > > of treating it as uninitialized, as kvmtool has done so far.
> > > 
> > > Signed-off-by: Suzuki K Poulose 
> > > Signed-off-by: Alexandru Elisei 
> > > ---
> > >  builtin-run.c | 65 +++
> > >  1 file changed, 60 insertions(+), 5 deletions(-)
> > > 
> > > diff --git a/builtin-run.c b/builtin-run.c
> > > index 2ef159cdb2a3..a49698d5b2fe 100644
> > > --- a/builtin-run.c
> > > +++ b/builtin-run.c
> > > @@ -49,9 +49,11 @@
> > >  #include 
> > >  #include 
> > >  
> > > -#define MB_SHIFT (20)
> > >  #define KB_SHIFT (10)
> > > +#define MB_SHIFT (20)
> > >  #define GB_SHIFT (30)
> > > +#define TB_SHIFT (40)
> > > +#define PB_SHIFT (50)  
> > 
> > Can we lose the parentheses?  
> 
> Yes.
> 
> >   
> > >  
> > >  __thread struct kvm_cpu *current_kvm_cpu;
> > >  
> > > @@ -87,6 +89,60 @@ void kvm_run_set_wrapper_sandbox(void)
> > >   kvm_run_wrapper = KVM_RUN_SANDBOX;
> > >  }
> > >  
> > > +static int parse_mem_unit(char **next)
> > > +{
> > > + int shift = -1;
> > > +
> > > + switch (**next) {
> > > + case 'B': case 'b': shift = 0; break;
> > > + case 'K': case 'k': shift = KB_SHIFT; break;
> > > + case 'M': case 'm': shift = MB_SHIFT; break;
> > > + case 'G': case 'g': shift = GB_SHIFT; break;
> > > + case 'T': case 't': shift = TB_SHIFT; break;
> > > + case 'P': case 'p': shift = PB_SHIFT; break;
> > > + }
> > > +
> > > + if (shift == -1) {
> > > + /* The default is megabytes. */
> > > + shift = MB_SHIFT;  
> > 
> > Doesn't that look better inside the switch/case?
> > default: return MB_SHIFT;  
> 
> I think that change alone breaks the logic.
> 
> The code needs to advance next if and only if it matches on one of the
> characters. I'll have a go at advancing next in each of the switch arms
> above (with the exception of the default one, which I'll add) to see how it
> ends up looking.

Mmh, but I meant:
{
switch (**next) {
case 'B': case 'b': shift = 0; break;
case 'K': case 'k': shift = KB_SHIFT; break;
case 'M': case 'm': shift = MB_SHIFT; break;
case 'G': case 'g': shift = GB_SHIFT; break;
case 'T': case 't': shift = TB_SHIFT; break;
case 'P': case 'p': shift = PB_SHIFT; break;
default: return MB_SHIFT;  
}

(*next)++;

return shift;
}

that should solve it, shouldn't it?

> 
> >   
> > > + } else {
> > > + (*next)++;
> > > + }
> > > +
> > > + return shift;
> > > +}
> > > +
> > > +static u64 parse_mem_option(const char *nptr, char **next)
> > > +{
> > > + u64 shift;
> > > + u64 val;
> > > +
> > > + val = strtoull(nptr, next, 10);
> > > + if (errno == ERANGE)
> > > + die("Memory too large: %s", nptr);  
> > 
> > strtoull does not clear errno if it succeeds, so it retains the
> > previous error value. So we would need to set errno to 0 just before
> > calling strtoull.  
> 
> This was intentional on my part, because I was under the impression that
> kvmtool treats all instances where errno != 0 as a fatal error. I think I
> was wrong about that, I see at least one instance when that isn't the case,
> in kvm_setup_guest_init -> extract_file. So it isn't a rule that a non-zero
> errno is a fatal error.
> 
> I'll change the code to zero errno before calling strtoull.

Thanks!

> 
> >   
> > > + shift = parse_mem_unit(next);
> > > +
> > > + if ((val << shift) < val)
> > > + die("Memory too large: %s", nptr);
> > > +

Re: [PATCH v3 kvmtool 06/13] arm/arm64: Fail if RAM size is too large for 32-bit guests

2022-06-01 Thread Andre Przywara
On Wed, 25 May 2022 12:23:38 +0100
Alexandru Elisei  wrote:

> For 64-bit guests, kvmtool exists with an error in kvm__get_vm_type() if
> the memory size is larger than what KVM supports. For 32-bit guests, the
> RAM size is silently rounded down to ARM_LOMAP_MAX_MEMORY in
> kvm__arch_init().
> 
> Be consistent and exit with an error when the user has configured the
> wrong RAM size for 32-bit guests.
> 
> Signed-off-by: Alexandru Elisei 

This patch looks fine, as it improves the situation and maintains the
current support level, but it turns out that the AArch32 memory limitation
is bogus: With LPAE (which is mandatory for any system supporting KVM),
there is no reason we can't have memory beyond 4GB of guest PA.
In fact, after removing this check, I managed to boot a 32GB AArch32 guest
just fine (on a Juno), and a 2919MB guest on an ARMv7 box.
It might be useful to lift this limit, as this allows easy testing of the
arm(32) kernel's highmem support, but this would be a separate patch, I
guess.

Reviewed-by: Andre Przywara 

Cheers,
Andre
 

> ---
>  arm/aarch32/kvm.c | 4 
>  arm/aarch64/kvm.c | 5 +
>  arm/kvm.c | 2 +-
>  3 files changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/arm/aarch32/kvm.c b/arm/aarch32/kvm.c
> index ae33ac92479a..9d68d7a15ee2 100644
> --- a/arm/aarch32/kvm.c
> +++ b/arm/aarch32/kvm.c
> @@ -2,4 +2,8 @@
>  
>  void kvm__arch_validate_cfg(struct kvm *kvm)
>  {
> + if (kvm->cfg.ram_size > ARM_LOMAP_MAX_MEMORY) {
> + die("RAM size 0x%llx exceeds maximum allowed 0x%llx",
> + kvm->cfg.ram_size, ARM_LOMAP_MAX_MEMORY);
> + }
>  }
> diff --git a/arm/aarch64/kvm.c b/arm/aarch64/kvm.c
> index ca348f118a56..2134528bf7f2 100644
> --- a/arm/aarch64/kvm.c
> +++ b/arm/aarch64/kvm.c
> @@ -39,6 +39,11 @@ int vcpu_affinity_parser(const struct option *opt, const 
> char *arg, int unset)
>  
>  void kvm__arch_validate_cfg(struct kvm *kvm)
>  {
> + if (kvm->cfg.arch.aarch32_guest &&
> + kvm->cfg.ram_size > ARM_LOMAP_MAX_MEMORY) {
> + die("RAM size 0x%llx exceeds maximum allowed 0x%llx",
> + kvm->cfg.ram_size, ARM_LOMAP_MAX_MEMORY);
> + }
>  }
>  
>  /*
> diff --git a/arm/kvm.c b/arm/kvm.c
> index c5913000e1ed..af0feae495d7 100644
> --- a/arm/kvm.c
> +++ b/arm/kvm.c
> @@ -65,7 +65,7 @@ void kvm__arch_init(struct kvm *kvm, const char 
> *hugetlbfs_path, u64 ram_size)
>* If using THP, then our minimal alignment becomes 2M.
>* 2M trumps 64K, so let's go with that.
>*/
> - kvm->ram_size = min(ram_size, (u64)ARM_MAX_MEMORY(kvm));
> + kvm->ram_size = ram_size;
>   kvm->arch.ram_alloc_size = kvm->ram_size + SZ_2M;
>   kvm->arch.ram_alloc_start = mmap_anon_or_hugetlbfs(kvm, hugetlbfs_path,
>   kvm->arch.ram_alloc_size);

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v3 kvmtool 10/13] kvm__arch_init: Remove hugetlbfs_path and ram_size as parameters

2022-06-01 Thread Andre Przywara
On Wed, 25 May 2022 12:23:42 +0100
Alexandru Elisei  wrote:

> From: Julien Grall 
> 
> The kvm struct already contains a pointer to the configuration, which
> contains both hugetlbfs_path and ram_size, so is it not necessary to pass
> them as arguments to kvm__arch_init().
> 
> Signed-off-by: Julien Grall 
> Signed-off-by: Alexandru Elisei 

Like that cleanup.

Reviewed-by: Andre Przywara 

Cheers,
Andre

> ---
>  arm/kvm.c | 7 ---
>  include/kvm/kvm.h | 2 +-
>  kvm.c | 2 +-
>  mips/kvm.c| 7 ---
>  powerpc/kvm.c | 5 +++--
>  riscv/kvm.c   | 7 ---
>  x86/kvm.c | 4 +++-
>  7 files changed, 20 insertions(+), 14 deletions(-)
> 
> diff --git a/arm/kvm.c b/arm/kvm.c
> index af0feae495d7..bd44aa350796 100644
> --- a/arm/kvm.c
> +++ b/arm/kvm.c
> @@ -57,7 +57,7 @@ void kvm__arch_set_cmdline(char *cmdline, bool video)
>  {
>  }
>  
> -void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 
> ram_size)
> +void kvm__arch_init(struct kvm *kvm)
>  {
>   /*
>* Allocate guest memory. We must align our buffer to 64K to
> @@ -65,9 +65,10 @@ void kvm__arch_init(struct kvm *kvm, const char 
> *hugetlbfs_path, u64 ram_size)
>* If using THP, then our minimal alignment becomes 2M.
>* 2M trumps 64K, so let's go with that.
>*/
> - kvm->ram_size = ram_size;
> + kvm->ram_size = kvm->cfg.ram_size;
>   kvm->arch.ram_alloc_size = kvm->ram_size + SZ_2M;
> - kvm->arch.ram_alloc_start = mmap_anon_or_hugetlbfs(kvm, hugetlbfs_path,
> + kvm->arch.ram_alloc_start = mmap_anon_or_hugetlbfs(kvm,
> + kvm->cfg.hugetlbfs_path,
>   kvm->arch.ram_alloc_size);
>  
>   if (kvm->arch.ram_alloc_start == MAP_FAILED)
> diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
> index 9f7b2fb26e95..640b76c095f9 100644
> --- a/include/kvm/kvm.h
> +++ b/include/kvm/kvm.h
> @@ -189,7 +189,7 @@ void kvm__remove_socket(const char *name);
>  
>  void kvm__arch_validate_cfg(struct kvm *kvm);
>  void kvm__arch_set_cmdline(char *cmdline, bool video);
> -void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 
> ram_size);
> +void kvm__arch_init(struct kvm *kvm);
>  void kvm__arch_delete_ram(struct kvm *kvm);
>  int kvm__arch_setup_firmware(struct kvm *kvm);
>  int kvm__arch_free_firmware(struct kvm *kvm);
> diff --git a/kvm.c b/kvm.c
> index 952ef1fbb41c..42b881217df6 100644
> --- a/kvm.c
> +++ b/kvm.c
> @@ -479,7 +479,7 @@ int kvm__init(struct kvm *kvm)
>   goto err_vm_fd;
>   }
>  
> - kvm__arch_init(kvm, kvm->cfg.hugetlbfs_path, kvm->cfg.ram_size);
> + kvm__arch_init(kvm);
>  
>   INIT_LIST_HEAD(>mem_banks);
>   kvm__init_ram(kvm);
> diff --git a/mips/kvm.c b/mips/kvm.c
> index f5b137f46dff..d8610cf81b94 100644
> --- a/mips/kvm.c
> +++ b/mips/kvm.c
> @@ -61,12 +61,13 @@ void kvm__arch_set_cmdline(char *cmdline, bool video)
>  }
>  
>  /* Architecture-specific KVM init */
> -void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 
> ram_size)
> +void kvm__arch_init(struct kvm *kvm)
>  {
>   int ret;
>  
> - kvm->ram_start = mmap_anon_or_hugetlbfs(kvm, hugetlbfs_path, ram_size);
> - kvm->ram_size = ram_size;
> + kvm->ram_size = kvm->cfg.ram_size;
> + kvm->ram_start = mmap_anon_or_hugetlbfs(kvm, kvm->cfg.hugetlbfs_path,
> + kvm->ram_size);
>  
>   if (kvm->ram_start == MAP_FAILED)
>   die("out of memory");
> diff --git a/powerpc/kvm.c b/powerpc/kvm.c
> index 3215b579f5dc..d281b070fd0e 100644
> --- a/powerpc/kvm.c
> +++ b/powerpc/kvm.c
> @@ -92,12 +92,13 @@ void kvm__arch_set_cmdline(char *cmdline, bool video)
>  }
>  
>  /* Architecture-specific KVM init */
> -void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 
> ram_size)
> +void kvm__arch_init(struct kvm *kvm)
>  {
> + const char *hugetlbfs_path = kvm->cfg.hugetlbfs_path;
>   int cap_ppc_rma;
>   unsigned long hpt;
>  
> - kvm->ram_size   = ram_size;
> + kvm->ram_size   = kvm->cfg.ram_size;
>  
>   /* Map "default" hugetblfs path to the standard 16M mount point */
>   if (hugetlbfs_path && !strcmp(hugetlbfs_path, "default"))
> diff --git a/riscv/kvm.c b/riscv/kvm.c
> index 7fb496282f4c..c46660772aa0 100644
> --- a/riscv/kvm.c
> +++ b/riscv/kvm.c
> @@ -56,7 +56,7 @@ void kvm__arch_set_cmdline(char *cmdline, bool video)
>  {
>  }
&g

Re: [PATCH v3 kvmtool 04/13] builtin-run: Rework RAM size validation

2022-06-01 Thread Andre Przywara
On Wed, 25 May 2022 12:23:36 +0100
Alexandru Elisei  wrote:

> host_ram_size() uses sysconf() to calculate the available ram, and
> sysconf() can fail. When that happens, host_ram_size() returns 0. kvmtool
> warns the user when the configured VM ram size exceeds the size of the
> host's memory, but doesn't take into account that host_ram_size() can
> return 0. If the function returns zero, skip the warning.
> 
> Since this can only happen when the user sets the memory size (via the
> -m/--mem command line argument), skip the check entirely if the user hasn't
> set it. Move the check to kvm_run_validate_cfg(), as it checks for valid
> user configuration.
> 
> Signed-off-by: Alexandru Elisei 
> ---
>  builtin-run.c | 20 +---
>  1 file changed, 13 insertions(+), 7 deletions(-)
> 
> diff --git a/builtin-run.c b/builtin-run.c
> index 4fc7cbed1d17..b1accbce7da3 100644
> --- a/builtin-run.c
> +++ b/builtin-run.c
> @@ -509,6 +509,8 @@ static void kvm_run_set_real_cmdline(struct kvm *kvm)
>  
>  static void kvm_run_validate_cfg(struct kvm *kvm)
>  {
> + u64 available_ram;

Just a nit, you can pull this declaration inside the if statement below,
IIUC you will only need it there.

Otherwise looks fine:

Reviewed-by: Andre Przywara 

> +
>   if (kvm->cfg.kernel_filename && kvm->cfg.firmware_filename)
>   die("Only one of --kernel or --firmware can be specified");
>  
> @@ -518,6 +520,17 @@ static void kvm_run_validate_cfg(struct kvm *kvm)
>  
>   if (kvm->cfg.firmware_filename && kvm->cfg.initrd_filename)
>   pr_warning("Ignoring initrd file when loading a firmware 
> image");
> +
> + if (kvm->cfg.ram_size) {
> + /* User specifies RAM size in megabytes. */
> + kvm->cfg.ram_size <<= MB_SHIFT;
> + available_ram = host_ram_size();
> + if (available_ram && kvm->cfg.ram_size > available_ram) {
> + pr_warning("Guest memory size %lluMB exceeds host 
> physical RAM size %lluMB",
> + (unsigned long long)kvm->cfg.ram_size >> 
> MB_SHIFT,
> + (unsigned long long)available_ram >> MB_SHIFT);
> + }
> + }
>  }
>  
>  static struct kvm *kvm_cmd_run_init(int argc, const char **argv)
> @@ -596,13 +609,6 @@ static struct kvm *kvm_cmd_run_init(int argc, const char 
> **argv)
>  
>   if (!kvm->cfg.ram_size)
>   kvm->cfg.ram_size = get_ram_size(kvm->cfg.nrcpus);
> - else
> - kvm->cfg.ram_size <<= MB_SHIFT;
> -
> - if (kvm->cfg.ram_size > host_ram_size())
> - pr_warning("Guest memory size %lluMB exceeds host physical RAM 
> size %lluMB",
> - (unsigned long long)kvm->cfg.ram_size >> MB_SHIFT,
> - (unsigned long long)host_ram_size() >> MB_SHIFT);
>  
>   if (!kvm->cfg.dev)
>   kvm->cfg.dev = DEFAULT_KVM_DEV;

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v3 kvmtool 11/13] arm/arm64: Consolidate RAM initialization in kvm__init_ram()

2022-06-01 Thread Andre Przywara
On Wed, 25 May 2022 12:23:43 +0100
Alexandru Elisei  wrote:

Hi,

> From: Julien Grall 
> 
> RAM initialization is unnecessarily split between kvm__init_ram() and
> kvm__arch_init(). Move all code related to RAM initialization to
> kvm__init_ram(), making the code easier to follow and to modify.
> 
> One thing to note is that the initialization order is slightly altered:
> kvm__arch_enable_mte() and gic__create() are now called before mmap'ing the
> guest RAM. That is perfectly fine, as they don't use the host's mapping of
> the guest memory.
> 
> Signed-off-by: Julien Grall 
> Signed-off-by: Alexandru Elisei 

I can confirm that this is just a code move, also MTE and GIC init do not
seem to rely on RAM in any way.

Reviewed-by: Andre Przywara 

Cheers,
Andre

> ---
>  arm/kvm.c | 52 ++--
>  1 file changed, 26 insertions(+), 26 deletions(-)
> 
> diff --git a/arm/kvm.c b/arm/kvm.c
> index bd44aa350796..abcccfabf59e 100644
> --- a/arm/kvm.c
> +++ b/arm/kvm.c
> @@ -26,9 +26,34 @@ bool kvm__arch_cpu_supports_vm(void)
>  
>  void kvm__init_ram(struct kvm *kvm)
>  {
> - int err;
>   u64 phys_start, phys_size;
>   void *host_mem;
> + int err;
> +
> + /*
> +  * Allocate guest memory. We must align our buffer to 64K to
> +  * correlate with the maximum guest page size for virtio-mmio.
> +  * If using THP, then our minimal alignment becomes 2M.
> +  * 2M trumps 64K, so let's go with that.
> +  */
> + kvm->ram_size = kvm->cfg.ram_size;
> + kvm->arch.ram_alloc_size = kvm->ram_size + SZ_2M;
> + kvm->arch.ram_alloc_start = mmap_anon_or_hugetlbfs(kvm,
> + kvm->cfg.hugetlbfs_path,
> + kvm->arch.ram_alloc_size);
> +
> + if (kvm->arch.ram_alloc_start == MAP_FAILED)
> + die("Failed to map %lld bytes for guest memory (%d)",
> + kvm->arch.ram_alloc_size, errno);
> +
> + kvm->ram_start = (void *)ALIGN((unsigned long)kvm->arch.ram_alloc_start,
> + SZ_2M);
> +
> + madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
> + MADV_MERGEABLE);
> +
> + madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
> + MADV_HUGEPAGE);
>  
>   phys_start  = ARM_MEMORY_AREA;
>   phys_size   = kvm->ram_size;
> @@ -59,31 +84,6 @@ void kvm__arch_set_cmdline(char *cmdline, bool video)
>  
>  void kvm__arch_init(struct kvm *kvm)
>  {
> - /*
> -  * Allocate guest memory. We must align our buffer to 64K to
> -  * correlate with the maximum guest page size for virtio-mmio.
> -  * If using THP, then our minimal alignment becomes 2M.
> -  * 2M trumps 64K, so let's go with that.
> -  */
> - kvm->ram_size = kvm->cfg.ram_size;
> - kvm->arch.ram_alloc_size = kvm->ram_size + SZ_2M;
> - kvm->arch.ram_alloc_start = mmap_anon_or_hugetlbfs(kvm,
> - kvm->cfg.hugetlbfs_path,
> - kvm->arch.ram_alloc_size);
> -
> - if (kvm->arch.ram_alloc_start == MAP_FAILED)
> - die("Failed to map %lld bytes for guest memory (%d)",
> - kvm->arch.ram_alloc_size, errno);
> -
> - kvm->ram_start = (void *)ALIGN((unsigned long)kvm->arch.ram_alloc_start,
> - SZ_2M);
> -
> - madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
> - MADV_MERGEABLE);
> -
> - madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
> - MADV_HUGEPAGE);
> -
>   /* Create the virtual GIC. */
>   if (gic__create(kvm, kvm->cfg.arch.irqchip))
>   die("Failed to create virtual GIC");

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v3 kvmtool 12/13] Introduce kvm__arch_default_ram_address()

2022-06-01 Thread Andre Przywara
On Wed, 25 May 2022 12:23:44 +0100
Alexandru Elisei  wrote:

> Add a new function, kvm__arch_default_ram_address(), which returns the
> default address for guest RAM for each architecture.
> 
> Signed-off-by: Alexandru Elisei 

Reviewed-by: Andre Przywara 

Cheers,
Andre

> ---
>  arm/aarch32/kvm.c | 5 +
>  arm/aarch64/kvm.c | 5 +
>  include/kvm/kvm.h | 1 +
>  mips/kvm.c| 5 +
>  powerpc/kvm.c | 5 +
>  riscv/kvm.c   | 5 +
>  x86/kvm.c | 5 +
>  7 files changed, 31 insertions(+)
> 
> diff --git a/arm/aarch32/kvm.c b/arm/aarch32/kvm.c
> index 9d68d7a15ee2..768a56bbb5b4 100644
> --- a/arm/aarch32/kvm.c
> +++ b/arm/aarch32/kvm.c
> @@ -7,3 +7,8 @@ void kvm__arch_validate_cfg(struct kvm *kvm)
>   kvm->cfg.ram_size, ARM_LOMAP_MAX_MEMORY);
>   }
>  }
> +
> +u64 kvm__arch_default_ram_address(void)
> +{
> + return ARM_MEMORY_AREA;
> +}
> diff --git a/arm/aarch64/kvm.c b/arm/aarch64/kvm.c
> index 2134528bf7f2..357936844046 100644
> --- a/arm/aarch64/kvm.c
> +++ b/arm/aarch64/kvm.c
> @@ -46,6 +46,11 @@ void kvm__arch_validate_cfg(struct kvm *kvm)
>   }
>  }
>  
> +u64 kvm__arch_default_ram_address(void)
> +{
> + return ARM_MEMORY_AREA;
> +}
> +
>  /*
>   * Return the TEXT_OFFSET value that the guest kernel expects. Note
>   * that pre-3.17 kernels expose this value using the native endianness
> diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
> index 640b76c095f9..360430b78b1e 100644
> --- a/include/kvm/kvm.h
> +++ b/include/kvm/kvm.h
> @@ -190,6 +190,7 @@ void kvm__remove_socket(const char *name);
>  void kvm__arch_validate_cfg(struct kvm *kvm);
>  void kvm__arch_set_cmdline(char *cmdline, bool video);
>  void kvm__arch_init(struct kvm *kvm);
> +u64 kvm__arch_default_ram_address(void);
>  void kvm__arch_delete_ram(struct kvm *kvm);
>  int kvm__arch_setup_firmware(struct kvm *kvm);
>  int kvm__arch_free_firmware(struct kvm *kvm);
> diff --git a/mips/kvm.c b/mips/kvm.c
> index d8610cf81b94..4cbc9907731b 100644
> --- a/mips/kvm.c
> +++ b/mips/kvm.c
> @@ -12,6 +12,11 @@ struct kvm_ext kvm_req_ext[] = {
>   { 0, 0 }
>  };
>  
> +u64 kvm__arch_default_ram_address(void)
> +{
> + return 0;
> +}
> +
>  void kvm__arch_validate_cfg(struct kvm *kvm)
>  {
>  }
> diff --git a/powerpc/kvm.c b/powerpc/kvm.c
> index d281b070fd0e..7b0d0669aff4 100644
> --- a/powerpc/kvm.c
> +++ b/powerpc/kvm.c
> @@ -48,6 +48,11 @@ struct kvm_ext kvm_req_ext[] = {
>   { 0, 0 }
>  };
>  
> +u64 kvm__arch_default_ram_address(void)
> +{
> + return 0;
> +}
> +
>  void kvm__arch_validate_cfg(struct kvm *kvm)
>  {
>  }
> diff --git a/riscv/kvm.c b/riscv/kvm.c
> index c46660772aa0..4d6f5cb57ac8 100644
> --- a/riscv/kvm.c
> +++ b/riscv/kvm.c
> @@ -13,6 +13,11 @@ struct kvm_ext kvm_req_ext[] = {
>   { 0, 0 },
>  };
>  
> +u64 kvm__arch_default_ram_address(void)
> +{
> + return RISCV_RAM;
> +}
> +
>  void kvm__arch_validate_cfg(struct kvm *kvm)
>  {
>  }
> diff --git a/x86/kvm.c b/x86/kvm.c
> index 24b0305a1841..328fa7500596 100644
> --- a/x86/kvm.c
> +++ b/x86/kvm.c
> @@ -35,6 +35,11 @@ struct kvm_ext kvm_req_ext[] = {
>   { 0, 0 }
>  };
>  
> +u64 kvm__arch_default_ram_address(void)
> +{
> + return 0;
> +}
> +
>  void kvm__arch_validate_cfg(struct kvm *kvm)
>  {
>  }

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v3 kvmtool 09/13] builtin_run: Allow standard size specifiers for memory

2022-06-01 Thread Andre Przywara
On Wed, 25 May 2022 12:23:41 +0100
Alexandru Elisei  wrote:

Hi,

> From: Suzuki K Poulose 
> 
> Allow the user to use the standard B (bytes), K (kilobytes), M (megabytes),
> G (gigabytes), T (terabytes) and P (petabytes) suffixes for memory size.
> When none are specified, the default is megabytes.
> 
> Also raise an error if the guest specifies 0 as the memory size, instead
> of treating it as uninitialized, as kvmtool has done so far.
> 
> Signed-off-by: Suzuki K Poulose 
> Signed-off-by: Alexandru Elisei 
> ---
>  builtin-run.c | 65 +++
>  1 file changed, 60 insertions(+), 5 deletions(-)
> 
> diff --git a/builtin-run.c b/builtin-run.c
> index 2ef159cdb2a3..a49698d5b2fe 100644
> --- a/builtin-run.c
> +++ b/builtin-run.c
> @@ -49,9 +49,11 @@
>  #include 
>  #include 
>  
> -#define MB_SHIFT (20)
>  #define KB_SHIFT (10)
> +#define MB_SHIFT (20)
>  #define GB_SHIFT (30)
> +#define TB_SHIFT (40)
> +#define PB_SHIFT (50)

Can we lose the parentheses?

>  
>  __thread struct kvm_cpu *current_kvm_cpu;
>  
> @@ -87,6 +89,60 @@ void kvm_run_set_wrapper_sandbox(void)
>   kvm_run_wrapper = KVM_RUN_SANDBOX;
>  }
>  
> +static int parse_mem_unit(char **next)
> +{
> + int shift = -1;
> +
> + switch (**next) {
> + case 'B': case 'b': shift = 0; break;
> + case 'K': case 'k': shift = KB_SHIFT; break;
> + case 'M': case 'm': shift = MB_SHIFT; break;
> + case 'G': case 'g': shift = GB_SHIFT; break;
> + case 'T': case 't': shift = TB_SHIFT; break;
> + case 'P': case 'p': shift = PB_SHIFT; break;
> + }
> +
> + if (shift == -1) {
> + /* The default is megabytes. */
> + shift = MB_SHIFT;

Doesn't that look better inside the switch/case?
default: return MB_SHIFT;

> + } else {
> + (*next)++;
> + }
> +
> + return shift;
> +}
> +
> +static u64 parse_mem_option(const char *nptr, char **next)
> +{
> + u64 shift;
> + u64 val;
> +
> + val = strtoull(nptr, next, 10);
> + if (errno == ERANGE)
> + die("Memory too large: %s", nptr);

strtoull does not clear errno if it succeeds, so it retains the
previous error value. So we would need to set errno to 0 just before
calling strtoull.

> + shift = parse_mem_unit(next);
> +
> + if ((val << shift) < val)
> + die("Memory too large: %s", nptr);
> +
> + return val << shift;
> +}
> +
> +static int mem_parser(const struct option *opt, const char *arg, int unset)
> +{
> + struct kvm *kvm = opt->ptr;
> + char *next;
> +
> + kvm->cfg.ram_size = parse_mem_option(arg, );
> + if (kvm->cfg.ram_size == 0)
> + die("Invalid RAM size: %s", arg);

Does 0 hold any significant value (anymore)? I think we die() if we
encounter invalid values in parse_mem_option()?

Cheers,
Andre

> +
> + if (*next != '\0')
> + die("Invalid memory specifier: %s", arg);
> +
> + return 0;
> +}
> +
>  #ifndef OPT_ARCH_RUN
>  #define OPT_ARCH_RUN(...)
>  #endif
> @@ -97,8 +153,9 @@ void kvm_run_set_wrapper_sandbox(void)
>   OPT_STRING('\0', "name", &(cfg)->guest_name, "guest name",  \
>   "A name for the guest"),\
>   OPT_INTEGER('c', "cpus", &(cfg)->nrcpus, "Number of CPUs"), \
> - OPT_U64('m', "mem", &(cfg)->ram_size, "Virtual machine memory"  \
> - " size in MB."),\
> + OPT_CALLBACK('m', "mem", NULL, "size[BKMGTP]",  \
> +  "Virtual machine memory size, by default measured" \
> +  " in megabytes (M)", mem_parser, kvm), \
>   OPT_CALLBACK('d', "disk", kvm, "image or rootfs_dir", "Disk "   \
>   " image or rootfs directory", img_name_parser,  \
>   kvm),   \
> @@ -522,8 +579,6 @@ static void kvm_run_validate_cfg(struct kvm *kvm)
>   pr_warning("Ignoring initrd file when loading a firmware 
> image");
>  
>   if (kvm->cfg.ram_size) {
> - /* User specifies RAM size in megabytes. */
> - kvm->cfg.ram_size <<= MB_SHIFT;
>   available_ram = host_ram_size();
>   if (available_ram && kvm->cfg.ram_size > available_ram) {
>   pr_warning("Guest memory size %lluMB exceeds host 
> physical RAM size %lluMB",

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v3 kvmtool 13/13] arm64: Allow the user to specify the RAM base address

2022-06-01 Thread Andre Przywara
On Wed, 25 May 2022 12:23:45 +0100
Alexandru Elisei  wrote:

Hi,

> Allow the user to specify the RAM base address by using -m/--mem size@addr
> command line argument. The base address must be above 2GB, as to not
> overlap with the MMIO I/O region.
> 
> Signed-off-by: Alexandru Elisei 
> ---
>  arm/aarch64/include/kvm/kvm-arch.h |  2 ++
>  arm/aarch64/kvm.c  | 14 
>  arm/kvm.c  |  7 --
>  builtin-run.c  | 36 ++
>  include/kvm/kvm-config.h   |  1 +
>  include/kvm/kvm.h  | 12 ++
>  include/linux/sizes.h  |  2 ++
>  7 files changed, 64 insertions(+), 10 deletions(-)
> 
> diff --git a/arm/aarch64/include/kvm/kvm-arch.h 
> b/arm/aarch64/include/kvm/kvm-arch.h
> index ff857ca6e7b4..02d09a413831 100644
> --- a/arm/aarch64/include/kvm/kvm-arch.h
> +++ b/arm/aarch64/include/kvm/kvm-arch.h
> @@ -10,6 +10,8 @@ void kvm__arch_enable_mte(struct kvm *kvm);
>  
>  #define MAX_PAGE_SIZESZ_64K
>  
> +#define ARCH_HAS_CFG_RAM_ADDRESS 1
> +
>  #include "arm-common/kvm-arch.h"
>  
>  #endif /* KVM__KVM_ARCH_H */
> diff --git a/arm/aarch64/kvm.c b/arm/aarch64/kvm.c
> index 357936844046..54200c9eec9d 100644
> --- a/arm/aarch64/kvm.c
> +++ b/arm/aarch64/kvm.c
> @@ -4,6 +4,7 @@
>  
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  
> @@ -39,10 +40,15 @@ int vcpu_affinity_parser(const struct option *opt, const 
> char *arg, int unset)
>  
>  void kvm__arch_validate_cfg(struct kvm *kvm)
>  {
> +
> + if (kvm->cfg.ram_addr < ARM_MEMORY_AREA) {
> + die("RAM address is below the I/O region ending at %luGB",
> + ARM_MEMORY_AREA >> 30);
> + }
> +
>   if (kvm->cfg.arch.aarch32_guest &&
> - kvm->cfg.ram_size > ARM_LOMAP_MAX_MEMORY) {
> - die("RAM size 0x%llx exceeds maximum allowed 0x%llx",
> - kvm->cfg.ram_size, ARM_LOMAP_MAX_MEMORY);
> + kvm->cfg.ram_addr + kvm->cfg.ram_size > SZ_4G) {
> +     die("RAM extends above 4GB");

As mentioned in the other patch, this is actually no problem at all, but
as this patch just retains the current check, that's fine, for now.

The rest looks good, and it seems to work now.

Reviewed-by: Andre Przywara 

Cheers,
Andre

>   }
>  }
>  
> @@ -117,7 +123,7 @@ int kvm__get_vm_type(struct kvm *kvm)
>   return 0;
>  
>   /* Otherwise, compute the minimal required IPA size */
> - max_ipa = ARM_MEMORY_AREA + kvm->cfg.ram_size - 1;
> + max_ipa = kvm->cfg.ram_addr + kvm->cfg.ram_size - 1;
>   ipa_bits = max(32, fls_long(max_ipa));
>   pr_debug("max_ipa %lx ipa_bits %d max_ipa_bits %d",
>max_ipa, ipa_bits, max_ipa_bits);
> diff --git a/arm/kvm.c b/arm/kvm.c
> index abcccfabf59e..d51cc15d8b1c 100644
> --- a/arm/kvm.c
> +++ b/arm/kvm.c
> @@ -55,7 +55,7 @@ void kvm__init_ram(struct kvm *kvm)
>   madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
>   MADV_HUGEPAGE);
>  
> - phys_start  = ARM_MEMORY_AREA;
> + phys_start  = kvm->cfg.ram_addr;
>   phys_size   = kvm->ram_size;
>   host_mem= kvm->ram_start;
>  
> @@ -65,6 +65,9 @@ void kvm__init_ram(struct kvm *kvm)
>   "address 0x%llx [err %d]", phys_size, phys_start, err);
>  
>   kvm->arch.memory_guest_start = phys_start;
> +
> + pr_debug("RAM created at 0x%llx - 0x%llx",
> +  phys_start, phys_start + phys_size - 1);
>  }
>  
>  void kvm__arch_delete_ram(struct kvm *kvm)
> @@ -201,7 +204,7 @@ bool kvm__load_firmware(struct kvm *kvm, const char 
> *firmware_filename)
>  
>   /* For default firmware address, lets load it at the begining of RAM */
>   if (fw_addr == 0)
> - fw_addr = ARM_MEMORY_AREA;
> + fw_addr = kvm->arch.memory_guest_start;
>  
>   if (!validate_fw_addr(kvm, fw_addr))
>   die("Bad firmware destination: 0x%016llx", fw_addr);
> diff --git a/builtin-run.c b/builtin-run.c
> index a49698d5b2fe..68beaaa7c06f 100644
> --- a/builtin-run.c
> +++ b/builtin-run.c
> @@ -131,12 +131,21 @@ static u64 parse_mem_option(const char *nptr, char 
> **next)
>  static int mem_parser(const struct option *opt, const char *arg, int unset)
>  {
>   struct kvm *kvm = opt->ptr;
> - char *next;
> + char *next, *nptr;
>  
>   kvm->cfg.ram_size = parse_mem_option(arg, );
>   if (kvm->cfg.ram_size == 0)
>

Re: [PATCH v3 kvmtool 07/13] arm/arm64: Kill the ARM_MAX_MEMORY() macro

2022-06-01 Thread Andre Przywara
On Wed, 25 May 2022 12:23:39 +0100
Alexandru Elisei  wrote:

> For 32-bit guests, the maximum memory size is represented by the define
> ARM_LOMAP_MAX_MEMORY, which ARM_MAX_MEMORY() returns.
> 
> For 64-bit guests, the RAM size is checked against the maximum allowed
> by KVM in kvm__get_vm_type().
> 
> There are no users left for the ARM_MAX_MEMORY() macro, remove it.
> 
> Signed-off-by: Alexandru Elisei 

Reviewed-by: Andre Przywara 

Thanks,
Andre

> ---
>  arm/aarch32/include/kvm/kvm-arch.h |  2 --
>  arm/aarch64/include/kvm/kvm-arch.h | 16 
>  2 files changed, 18 deletions(-)
> 
> diff --git a/arm/aarch32/include/kvm/kvm-arch.h 
> b/arm/aarch32/include/kvm/kvm-arch.h
> index 5616b27e257e..467fb09175b8 100644
> --- a/arm/aarch32/include/kvm/kvm-arch.h
> +++ b/arm/aarch32/include/kvm/kvm-arch.h
> @@ -8,8 +8,6 @@
>  struct kvm;
>  static inline void kvm__arch_enable_mte(struct kvm *kvm) {}
>  
> -#define ARM_MAX_MEMORY(...)  ARM_LOMAP_MAX_MEMORY
> -
>  #define MAX_PAGE_SIZESZ_4K
>  
>  #include "arm-common/kvm-arch.h"
> diff --git a/arm/aarch64/include/kvm/kvm-arch.h 
> b/arm/aarch64/include/kvm/kvm-arch.h
> index 9124f6919d0f..ff857ca6e7b4 100644
> --- a/arm/aarch64/include/kvm/kvm-arch.h
> +++ b/arm/aarch64/include/kvm/kvm-arch.h
> @@ -8,22 +8,6 @@ unsigned long long kvm__arch_get_kern_offset(struct kvm 
> *kvm, int fd);
>  int kvm__arch_get_ipa_limit(struct kvm *kvm);
>  void kvm__arch_enable_mte(struct kvm *kvm);
>  
> -#define ARM_MAX_MEMORY(kvm)  ({  \
> - u64 max_ram;\
> - \
> - if ((kvm)->cfg.arch.aarch32_guest) {\
> - max_ram = ARM_LOMAP_MAX_MEMORY; \
> - } else {\
> - int ipabits = kvm__arch_get_ipa_limit(kvm); \
> - if (ipabits <= 0)   \
> - max_ram = ARM_HIMAP_MAX_MEMORY; \
> - else\
> - max_ram = (1ULL << ipabits) - ARM_MEMORY_AREA;  \
> - }   \
> - \
> - max_ram;\
> -})
> -
>  #define MAX_PAGE_SIZESZ_64K
>  
>  #include "arm-common/kvm-arch.h"

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v3 kvmtool 08/13] arm/arm64: Kill the ARM_HIMAP_MAX_MEMORY() macro

2022-06-01 Thread Andre Przywara
On Wed, 25 May 2022 12:23:40 +0100
Alexandru Elisei  wrote:

> The ARM_HIMAP_MAX_MEMORY() is a remnant of a time when KVM only supported
> 40 bits if IPA. There are no users left for this macro, remove it.
> 
> Signed-off-by: Alexandru Elisei 

Could be stashed together with the previous patch, I guess, but anyway:

Reviewed-by: Andre Przywara 

Cheers,
Andre

> ---
>  arm/include/arm-common/kvm-arch.h | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/arm/include/arm-common/kvm-arch.h 
> b/arm/include/arm-common/kvm-arch.h
> index fc55360d4d15..6d80aac17125 100644
> --- a/arm/include/arm-common/kvm-arch.h
> +++ b/arm/include/arm-common/kvm-arch.h
> @@ -65,7 +65,6 @@
>  
>  
>  #define ARM_LOMAP_MAX_MEMORY ((1ULL << 32) - ARM_MEMORY_AREA)
> -#define ARM_HIMAP_MAX_MEMORY ((1ULL << 40) - ARM_MEMORY_AREA)
>  
>  
>  #define KVM_IOEVENTFD_HAS_PIO0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v3 kvmtool 02/13] sizes.h: Make all sizes 64bit

2022-06-01 Thread Andre Przywara
On Wed, 25 May 2022 12:23:34 +0100
Alexandru Elisei  wrote:

Hi,

> Append ULL to all of the size definitions to make them 64bit and avoid
> overflows.

I am not fully convinced this is the best solution, as it deviates from
the kernel file, and just papers over issues at the call sites. I
acknowledge the pragmatic approach of trying to fix multiple problems at
once, but am wondering if we should use -fsanitize=undefined to identify
problematic code and fix it (I started doing this, actually).

Cheers,
Andre

> Reported-by: Andre Przywara 
> Signed-off-by: Alexandru Elisei 
> ---
>  include/linux/sizes.h | 64 +--
>  1 file changed, 32 insertions(+), 32 deletions(-)
> 
> diff --git a/include/linux/sizes.h b/include/linux/sizes.h
> index ce3e8150c174..b2b5c457cf1c 100644
> --- a/include/linux/sizes.h
> +++ b/include/linux/sizes.h
> @@ -8,40 +8,40 @@
>  #ifndef __LINUX_SIZES_H__
>  #define __LINUX_SIZES_H__
>  
> -#define SZ_1 0x0001
> -#define SZ_2 0x0002
> -#define SZ_4 0x0004
> -#define SZ_8 0x0008
> -#define SZ_160x0010
> -#define SZ_320x0020
> -#define SZ_640x0040
> -#define SZ_128   0x0080
> -#define SZ_256   0x0100
> -#define SZ_512   0x0200
> +#define SZ_1 0x0001ULL
> +#define SZ_2 0x0002ULL
> +#define SZ_4 0x0004ULL
> +#define SZ_8 0x0008ULL
> +#define SZ_160x0010ULL
> +#define SZ_320x0020ULL
> +#define SZ_640x0040ULL
> +#define SZ_128   0x0080ULL
> +#define SZ_256   0x0100ULL
> +#define SZ_512   0x0200ULL
>  
> -#define SZ_1K0x0400
> -#define SZ_2K0x0800
> -#define SZ_4K0x1000
> -#define SZ_8K0x2000
> -#define SZ_16K   0x4000
> -#define SZ_32K   0x8000
> -#define SZ_64K   0x0001
> -#define SZ_128K  0x0002
> -#define SZ_256K  0x0004
> -#define SZ_512K  0x0008
> +#define SZ_1K0x0400ULL
> +#define SZ_2K0x0800ULL
> +#define SZ_4K0x1000ULL
> +#define SZ_8K0x2000ULL
> +#define SZ_16K   0x4000ULL
> +#define SZ_32K   0x8000ULL
> +#define SZ_64K   0x0001ULL
> +#define SZ_128K  0x0002ULL
> +#define SZ_256K  0x0004ULL
> +#define SZ_512K  0x0008ULL
>  
> -#define SZ_1M0x0010
> -#define SZ_2M0x0020
> -#define SZ_4M0x0040
> -#define SZ_8M0x0080
> -#define SZ_16M   0x0100
> -#define SZ_32M   0x0200
> -#define SZ_64M   0x0400
> -#define SZ_128M  0x0800
> -#define SZ_256M  0x1000
> -#define SZ_512M  0x2000
> +#define SZ_1M0x0010ULL
> +#define SZ_2M0x0020ULL
> +#define SZ_4M0x0040ULL
> +#define SZ_8M0x0080ULL
> +#define SZ_16M   0x0100ULL
> +#define SZ_32M   0x0200ULL
> +#define SZ_64M   0x0400ULL
> +#define SZ_128M  0x0800ULL
> +#define SZ_256M  0x1000ULL
> +#define SZ_512M  0x2000ULL
>  
> -#define SZ_1G0x4000
> -#define SZ_2G0x8000
> +#define SZ_1G0x4000ULL
> +#define SZ_2G0x8000ULL
>  
>  #endif /* __LINUX_SIZES_H__ */

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH kvmtool 0/2] Add libfdt library

2022-05-26 Thread Andre Przywara
On Thu, 26 May 2022 16:30:56 +0100
Alexandru Elisei  wrote:

Hi Alex,

> I found it very difficult to cross-build kvmtool for all arches because for
> some architectures I couldn't get libfdt to install: either dtc wasn't
> compiling (x86 machine, Arch Linux, missing yaml.h include when building
> for arm and powerpc), or libfdt was not being found by Makefile after
> installing it (x86 machine, Debian 11, building for powerpc). It was
> possible to compile only libfdt and teach Makefile where to look for it,
> which is what I ended up doing, but in my opinion, that's not an ideal user
> experience.

Meh. Nobody said that userland cross compilation would be a walk in the
park, and this approach (cross-compiling and putting in SYSROOT) is the
canonical approach. When using a multiarch capable distro, this is easy
enough.
But I see that this is some major pain point for an otherwise rather "low
maintenance" tool, and libfdt is designed to be embedded, so I guess this
is fine, with the caveat mentioned below.

> This is my attempt at making compilation easier by pulling in the libfdt
> library and having kvmtool compile it when an architecture requires it. All
> the user needs to do now is to find a suitable cross-compiler toolchain
> with glibc included [1]*.
> 
> When making lkvm-static, the static version of libfdt is built (libfdt.a);
> for all other make targets the shared library is built.

So does that mean that the .so gets shipped with kvmtool? And it should be
installed as part of "make install"? I think that might bring up more
questions and problems, so do we want to leave the user some choice?
- The user brings their own libfdt. This should be the case for any clean
userland cross compilation, where you install target libraries in SYSROOT,
just for compilation, and have the .so file also on the actual target
system. This would also be best for native compilation. Current situation.
- The user decides to use the built-in libfdt, in which case that gets
always statically linked into the lkvm binary (which might still be
dynamically linked against libc), to avoid any conflict between the just
built version (.so), and the installed library on the target system.

Some projects choose this approach, where it gets decided at build time
which version to use ("system library" vs. built-in version). This is
either done automatically, because a system library is not found, or using
some user provided flag for configure/make.

If that sounds too involved, we could just always link in our libfdt copy
statically. And later revisit this when people complain.
Can you check by how much an otherwise dynamically linked kvmtool binary
grows when we link against libfdt.a?

Cheers,
Andre

> This only happens
> for those arches that require libfdt (arm, arm64, riscv, powerpc); libfdt
> is not built for MIPS and x86.
> 
> I am pretty happy with how libfdt has been integrated with the kvmtool
> build system. The only niggle is that the libfdt_clean target echoes the
> commands to remove the build artifacts:
> 
> $ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- clean
> Makefile:378: Skipping optional libraries: bfd zlib aio
>   CLEAN (libfdt)
> rm -f libfdt/*.o libfdt/libfdt.a libfdt/libfdt-1.6.1.so
> rm -f libfdt/libfdt.so.1
>   CLEAN
> 
> but I believe that's impossible to change without modifying the libfdt
> Makefile, which I don't want to do to keep it as easy as possible to update
> libfdt.
> 
> Made some quick measurement about how libfdt affects the build time when
> building from a clean directory (incremental builds do not rebuild libfdt):
> 
> - On a rockpro64, on the little core (Cortex-A53), running
> 
> $ time taskset -c 0 make
> 
> with libfdt takes an average of 90.721s (averaged over 3 runs, standard
> deviation 0.040s); without libfdt it takes 84.003s (averaged over 3 runs,
> stddev of 0.105s). That's a 6.718s absolute increase, or a 7.997% relative
> increase.
> 
> - On the same rockpro64, on the big core (Cortex-A72), running
> 
> $ time taskset -c 5 make
> 
> with libfdt takes an average of 45.078s (averaged over 3 runs, stddev of
> 0.060s); without libfdt it takes 41.836s (averaged over 3 runs, stddev of
> 0.065). That's a 3.242s absolute increase, or a 7.749% relative increase.
> 
> I believe that the ease of use more than justifies the increased
> compilation time.
> 
> Testing
> ===
> 
> On x86 host, compiled for x86, MIPS, arm, arm64, powerpc, riscv. Booted an
> x86 VM.
> 
> On arm64 host, compiled for arm64 and arm. I tried to cross-compile for
> other targets, but I couldn't find a cross-compiler toolchain for arm64
> hosts that included a libc implementation. The arm cross-compiler was
> downloaded from the developer.arm.com [2]. Ran kvm-unit-tests for arm64 and
> arm (on the arm64 version of kvmtool), and also booted a kernel.
> 
> *only for x86 hosts.
> 
> [1] https://toolchains.bootlin.com/
> [2] 
> 

[PATCH kvmtool 4/4] include: add new virtio uapi header files

2022-05-24 Thread Andre Przywara
Commit a08bb43a0c37 ("kvmtool: Copy Linux' up-to-date virtio headers")
copied in some of the virtio UAPI headers from the kernel tree, but
didn't include all of them, as we were relying on some of them being
provided by the distribution.

Now commit bc77bf49df6e ("stat: Add descriptions for new virtio_balloon
stat types") used some newer virtio balloon symbols, that some older
distros (e.g. Ubuntu 18.04) do not carry, which breaks compilation
there:
===
  CC   builtin-stat.o
builtin-stat.c: In function 'do_memstat':
builtin-stat.c:86:8: error: 'VIRTIO_BALLOON_S_HTLB_PGALLOC' undeclared (first 
use in this function); did you mean 'VIRTIO_BALLOON_S_AVAIL'?
   case VIRTIO_BALLOON_S_HTLB_PGALLOC:
^
VIRTIO_BALLOON_S_AVAIL
builtin-stat.c:86:8: note: each undeclared identifier is reported only once for 
each function it appears in
===

To fix this include the remaining virtio headers (those that we actually
need for kvmtool at the moment), from Linux v5.18.0.

Fixes: bc77bf49df6e ("stat: Add descriptions for new virtio_balloon stat types")
Signed-off-by: Andre Przywara 
---
 include/linux/virtio_9p.h  |  44 ++
 include/linux/virtio_balloon.h | 119 
 include/linux/virtio_blk.h | 203 +++
 include/linux/virtio_config.h  | 101 ++
 include/linux/virtio_console.h |  78 +++
 include/linux/virtio_pci.h | 208 
 include/linux/virtio_ring.h| 244 +
 include/linux/virtio_rng.h |   8 ++
 8 files changed, 1005 insertions(+)
 create mode 100644 include/linux/virtio_9p.h
 create mode 100644 include/linux/virtio_balloon.h
 create mode 100644 include/linux/virtio_blk.h
 create mode 100644 include/linux/virtio_config.h
 create mode 100644 include/linux/virtio_console.h
 create mode 100644 include/linux/virtio_pci.h
 create mode 100644 include/linux/virtio_ring.h
 create mode 100644 include/linux/virtio_rng.h

diff --git a/include/linux/virtio_9p.h b/include/linux/virtio_9p.h
new file mode 100644
index ..44104743
--- /dev/null
+++ b/include/linux/virtio_9p.h
@@ -0,0 +1,44 @@
+#ifndef _LINUX_VIRTIO_9P_H
+#define _LINUX_VIRTIO_9P_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in the
+ *documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ *may be used to endorse or promote products derived from this software
+ *without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 
IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE. */
+#include 
+#include 
+#include 
+
+/* The feature bitmap for virtio 9P */
+
+/* The mount point is specified in a config variable */
+#define VIRTIO_9P_MOUNT_TAG 0
+
+struct virtio_9p_config {
+   /* length of the tag name */
+   __virtio16 tag_len;
+   /* non-NULL terminated tag name */
+   __u8 tag[0];
+} __attribute__((packed));
+
+#endif /* _LINUX_VIRTIO_9P_H */
diff --git a/include/linux/virtio_balloon.h b/include/linux/virtio_balloon.h
new file mode 100644
index ..ddaa45e7
--- /dev/null
+++ b/include/linux/virtio_balloon.h
@@ -0,0 +1,119 @@
+#ifndef _LINUX_VIRTIO_BALLOON_H
+#define _LINUX_VIRTIO_BALLOON_H
+/* This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions

[PATCH kvmtool 3/4] include: update virtio UAPI headers

2022-05-24 Thread Andre Przywara
Commit a08bb43a0c37 ("kvmtool: Copy Linux' up-to-date virtio headers")
copied the kernel's virtio UAPI headers into the kvmtool tree, because
at the time some distros didn't include (all of) them in their kernel
headers package.
Let's update those copies, so that we can use newer features, if needed.

This syncs in the already existing copies of the headers from Linux
v5.18.0.

Signed-off-by: Andre Przywara 
---
 include/linux/virtio_ids.h   |  63 ---
 include/linux/virtio_net.h   | 200 +++
 include/linux/virtio_scsi.h  | 118 +++--
 include/linux/virtio_vsock.h |  16 ++-
 4 files changed, 305 insertions(+), 92 deletions(-)

diff --git a/include/linux/virtio_ids.h b/include/linux/virtio_ids.h
index 7de80eb7..80d76b75 100644
--- a/include/linux/virtio_ids.h
+++ b/include/linux/virtio_ids.h
@@ -29,17 +29,56 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE. */
 
-#define VIRTIO_ID_NET  1 /* virtio net */
-#define VIRTIO_ID_BLOCK2 /* virtio block */
-#define VIRTIO_ID_CONSOLE  3 /* virtio console */
-#define VIRTIO_ID_RNG  4 /* virtio rng */
-#define VIRTIO_ID_BALLOON  5 /* virtio balloon */
-#define VIRTIO_ID_RPMSG7 /* virtio remote processor messaging 
*/
-#define VIRTIO_ID_SCSI 8 /* virtio scsi */
-#define VIRTIO_ID_9P   9 /* 9p virtio console */
-#define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */
-#define VIRTIO_ID_CAIF12 /* Virtio caif */
-#define VIRTIO_ID_INPUT18 /* virtio input */
-#define VIRTIO_ID_VSOCK19 /* virtio vsock transport */
+#define VIRTIO_ID_NET  1 /* virtio net */
+#define VIRTIO_ID_BLOCK2 /* virtio block */
+#define VIRTIO_ID_CONSOLE  3 /* virtio console */
+#define VIRTIO_ID_RNG  4 /* virtio rng */
+#define VIRTIO_ID_BALLOON  5 /* virtio balloon */
+#define VIRTIO_ID_IOMEM6 /* virtio ioMemory */
+#define VIRTIO_ID_RPMSG7 /* virtio remote processor 
messaging */
+#define VIRTIO_ID_SCSI 8 /* virtio scsi */
+#define VIRTIO_ID_9P   9 /* 9p virtio console */
+#define VIRTIO_ID_MAC80211_WLAN10 /* virtio WLAN MAC */
+#define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */
+#define VIRTIO_ID_CAIF 12 /* Virtio caif */
+#define VIRTIO_ID_MEMORY_BALLOON   13 /* virtio memory balloon */
+#define VIRTIO_ID_GPU  16 /* virtio GPU */
+#define VIRTIO_ID_CLOCK17 /* virtio clock/timer */
+#define VIRTIO_ID_INPUT18 /* virtio input */
+#define VIRTIO_ID_VSOCK19 /* virtio vsock transport */
+#define VIRTIO_ID_CRYPTO   20 /* virtio crypto */
+#define VIRTIO_ID_SIGNAL_DIST  21 /* virtio signal distribution device 
*/
+#define VIRTIO_ID_PSTORE   22 /* virtio pstore device */
+#define VIRTIO_ID_IOMMU23 /* virtio IOMMU */
+#define VIRTIO_ID_MEM  24 /* virtio mem */
+#define VIRTIO_ID_SOUND25 /* virtio sound */
+#define VIRTIO_ID_FS   26 /* virtio filesystem */
+#define VIRTIO_ID_PMEM 27 /* virtio pmem */
+#define VIRTIO_ID_RPMB 28 /* virtio rpmb */
+#define VIRTIO_ID_MAC80211_HWSIM   29 /* virtio mac80211-hwsim */
+#define VIRTIO_ID_VIDEO_ENCODER30 /* virtio video encoder */
+#define VIRTIO_ID_VIDEO_DECODER31 /* virtio video decoder */
+#define VIRTIO_ID_SCMI 32 /* virtio SCMI */
+#define VIRTIO_ID_NITRO_SEC_MOD33 /* virtio nitro secure 
module*/
+#define VIRTIO_ID_I2C_ADAPTER  34 /* virtio i2c adapter */
+#define VIRTIO_ID_WATCHDOG 35 /* virtio watchdog */
+#define VIRTIO_ID_CAN  36 /* virtio can */
+#define VIRTIO_ID_DMABUF   37 /* virtio dmabuf */
+#define VIRTIO_ID_PARAM_SERV   38 /* virtio parameter server */
+#define VIRTIO_ID_AUDIO_POLICY 39 /* virtio audio policy */
+#define VIRTIO_ID_BT   40 /* virtio bluetooth */
+#define VIRTIO_ID_GPIO 41 /* virtio gpio */
+
+/*
+ * Virtio Transitional IDs
+ */
+
+#define VIRTIO_TRANS_ID_NET1000 /* transitional virtio net */
+#define VIRTIO_TRANS_ID_BLOCK  1001 /* transitional virtio block */
+#define VIRTIO_TRANS_ID_BALLOON1002 /* transitional virtio 
balloon */
+#define VIRTIO_TRANS_ID_CONSOLE1003 /* transitional virtio 
console */
+#define VIRTIO_TRANS_ID_SCSI   1004 /* transitional virtio SCSI */
+#define VIRTIO_TRANS_ID_RNG1005 /* transitional virtio rng */
+#define VIRTIO_TRANS_ID_9P 1009 /* transitional virtio 9p console 
*/
 
 #endif /* _LINUX_VIRTIO_IDS

[PATCH kvmtool 1/4] update virtio_mmio.h

2022-05-24 Thread Andre Przywara
At the time we pulled in virtio_mmio.h from the kernel tree (commit
a08bb43a0c37c "kvmtool: Copy Linux' up-to-date virtio headers"), this was
not an official UAPI header file, so wasn't stable and was not shipped
with distributions.
This has changed with Linux commit 51be7a9a261c ("virtio_mmio: expose
header to userspace"), so we can now use that file officially.
However before that the name of some symbols have changed, so we have to
adjust their usage in our source.

This pulls in virtio_mmio.h from Linux v5.18.0.

Signed-off-by: Andre Przywara 
---
 include/linux/virtio_mmio.h | 55 -
 virtio/mmio.c   |  8 +++---
 2 files changed, 52 insertions(+), 11 deletions(-)

diff --git a/include/linux/virtio_mmio.h b/include/linux/virtio_mmio.h
index 5c7b6f0d..0650f91b 100644
--- a/include/linux/virtio_mmio.h
+++ b/include/linux/virtio_mmio.h
@@ -51,23 +51,29 @@
 /* Virtio vendor ID - Read Only */
 #define VIRTIO_MMIO_VENDOR_ID  0x00c
 
-/* Bitmask of the features supported by the host
+/* Bitmask of the features supported by the device (host)
  * (32 bits per set) - Read Only */
-#define VIRTIO_MMIO_HOST_FEATURES  0x010
+#define VIRTIO_MMIO_DEVICE_FEATURES0x010
 
-/* Host features set selector - Write Only */
-#define VIRTIO_MMIO_HOST_FEATURES_SEL  0x014
+/* Device (host) features set selector - Write Only */
+#define VIRTIO_MMIO_DEVICE_FEATURES_SEL0x014
 
-/* Bitmask of features activated by the guest
+/* Bitmask of features activated by the driver (guest)
  * (32 bits per set) - Write Only */
-#define VIRTIO_MMIO_GUEST_FEATURES 0x020
+#define VIRTIO_MMIO_DRIVER_FEATURES0x020
 
 /* Activated features set selector - Write Only */
-#define VIRTIO_MMIO_GUEST_FEATURES_SEL 0x024
+#define VIRTIO_MMIO_DRIVER_FEATURES_SEL0x024
+
+
+#ifndef VIRTIO_MMIO_NO_LEGACY /* LEGACY DEVICES ONLY! */
 
 /* Guest's memory page size in bytes - Write Only */
 #define VIRTIO_MMIO_GUEST_PAGE_SIZE0x028
 
+#endif
+
+
 /* Queue selector - Write Only */
 #define VIRTIO_MMIO_QUEUE_SEL  0x030
 
@@ -77,12 +83,21 @@
 /* Queue size for the currently selected queue - Write Only */
 #define VIRTIO_MMIO_QUEUE_NUM  0x038
 
+
+#ifndef VIRTIO_MMIO_NO_LEGACY /* LEGACY DEVICES ONLY! */
+
 /* Used Ring alignment for the currently selected queue - Write Only */
 #define VIRTIO_MMIO_QUEUE_ALIGN0x03c
 
 /* Guest's PFN for the currently selected queue - Read Write */
 #define VIRTIO_MMIO_QUEUE_PFN  0x040
 
+#endif
+
+
+/* Ready bit for the currently selected queue - Read Write */
+#define VIRTIO_MMIO_QUEUE_READY0x044
+
 /* Queue notifier - Write Only */
 #define VIRTIO_MMIO_QUEUE_NOTIFY   0x050
 
@@ -95,6 +110,32 @@
 /* Device status register - Read Write */
 #define VIRTIO_MMIO_STATUS 0x070
 
+/* Selected queue's Descriptor Table address, 64 bits in two halves */
+#define VIRTIO_MMIO_QUEUE_DESC_LOW 0x080
+#define VIRTIO_MMIO_QUEUE_DESC_HIGH0x084
+
+/* Selected queue's Available Ring address, 64 bits in two halves */
+#define VIRTIO_MMIO_QUEUE_AVAIL_LOW0x090
+#define VIRTIO_MMIO_QUEUE_AVAIL_HIGH   0x094
+
+/* Selected queue's Used Ring address, 64 bits in two halves */
+#define VIRTIO_MMIO_QUEUE_USED_LOW 0x0a0
+#define VIRTIO_MMIO_QUEUE_USED_HIGH0x0a4
+
+/* Shared memory region id */
+#define VIRTIO_MMIO_SHM_SEL 0x0ac
+
+/* Shared memory region length, 64 bits in two halves */
+#define VIRTIO_MMIO_SHM_LEN_LOW 0x0b0
+#define VIRTIO_MMIO_SHM_LEN_HIGH0x0b4
+
+/* Shared memory region base address, 64 bits in two halves */
+#define VIRTIO_MMIO_SHM_BASE_LOW0x0b8
+#define VIRTIO_MMIO_SHM_BASE_HIGH   0x0bc
+
+/* Configuration atomicity value */
+#define VIRTIO_MMIO_CONFIG_GENERATION  0x0fc
+
 /* The config space is defined by each driver as
  * the per-driver configuration space - Read Write */
 #define VIRTIO_MMIO_CONFIG 0x100
diff --git a/virtio/mmio.c b/virtio/mmio.c
index d08da1eb..3782d55a 100644
--- a/virtio/mmio.c
+++ b/virtio/mmio.c
@@ -142,7 +142,7 @@ static void virtio_mmio_config_in(struct kvm_cpu *vcpu,
case VIRTIO_MMIO_INTERRUPT_STATUS:
ioport__write32(data, *(u32 *)(((void *)>hdr) + addr));
break;
-   case VIRTIO_MMIO_HOST_FEATURES:
+   case VIRTIO_MMIO_DEVICE_FEATURES:
if (vmmio->hdr.host_features_sel == 0)
val = vdev->ops->get_host_features(vmmio->kvm,
   vmmio->dev);
@@ -173,8 +173,8 @@ static void virtio_mmio_config_out(struct kvm_cpu *vcpu,
u32 val = 0;
 
switch (addr) {
-   case VIRTIO_MMIO_HOST_FEATURES_SEL:
-   case VIRTIO_MMIO_GUEST_FEATURES_SEL:
+   case VIRTIO_MMIO_DEVICE_FEATURES_SEL:
+   case VIRTIO_MMIO_DRIVER_FEATURES_SEL:
val = ioport__read32(data);
   

[PATCH kvmtool 2/4] util: include virtio UAPI headers in sync

2022-05-24 Thread Andre Przywara
We already have an update_headers.sh sync script, where we occasionally
update the KVM interface UAPI kernel headers into our tree.
So far this covered only the generic kvm.h, plus each architecture's
version of that file.
Commit  bc77bf49df6e ("stat: Add descriptions for new virtio_balloon
stat types") used newer virtio symbols, which some older distros do not
include in their kernel headers package. To help fixing this and to
avoid similar problems in the future, add the virtio headers to our sync
script, so that we can get the same, up-to-date versions of the headers
easily.

Signed-off-by: Andre Przywara 
---
 util/update_headers.sh | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/util/update_headers.sh b/util/update_headers.sh
index 5f9cd32d..789e2a42 100755
--- a/util/update_headers.sh
+++ b/util/update_headers.sh
@@ -9,6 +9,11 @@
 
 set -ue
 
+VIRTIO_LIST="virtio_9p.h virtio_balloon.h virtio_blk.h virtio_config.h \
+virtio_console.h virtio_ids.h virtio_mmio.h virtio_net.h \
+virtio_pci.h virtio_ring.h virtio_rng.h virtio_scsi.h \
+virtio_vsock.h"
+
 if [ "$#" -ge 1 ]
 then
LINUX_ROOT="$1"
@@ -25,6 +30,11 @@ fi
 
 cp -- "$LINUX_ROOT/include/uapi/linux/kvm.h" include/linux
 
+for header in $VIRTIO_LIST
+do
+   cp -- "$LINUX_ROOT/include/uapi/linux/$header" include/linux
+done
+
 unset KVMTOOL_PATH
 
 copy_optional_arch () {
-- 
2.25.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool 0/4] Update virtio headers (to fix build)

2022-05-24 Thread Andre Przywara
Since we implement some virtio devices in kvmtool, we were including
older copies of some virtio UAPI header files in our tree, but were
relying on some other headers to be provided by the distribution.
This leads to problems when we need to use newer virtio features (like
the recent virtio_balloon stat update), which breaks compilation on some
(older) distros.

To fix this and avoid similar problems in the future, just copy in the
virtio UAPI headers from the kernel tree, as we do already for the
actual KVM interface headers. To simplify future syncs, also update our
update_headers.sh script on the way.

Please have a look!

Cheers,
Andre

Andre Przywara (4):
  update virtio_mmio.h
  util: include virtio UAPI headers in sync
  include: update virtio UAPI headers
  include: add new virtio uapi header files

 include/linux/virtio_9p.h  |  44 ++
 include/linux/virtio_balloon.h | 119 
 include/linux/virtio_blk.h | 203 +++
 include/linux/virtio_config.h  | 101 ++
 include/linux/virtio_console.h |  78 +++
 include/linux/virtio_ids.h |  63 +++--
 include/linux/virtio_mmio.h|  55 +++-
 include/linux/virtio_net.h | 200 +++
 include/linux/virtio_pci.h | 208 
 include/linux/virtio_ring.h| 244 +
 include/linux/virtio_rng.h |   8 ++
 include/linux/virtio_scsi.h| 118 
 include/linux/virtio_vsock.h   |  16 ++-
 util/update_headers.sh |  10 ++
 virtio/mmio.c  |   8 +-
 15 files changed, 1372 insertions(+), 103 deletions(-)
 create mode 100644 include/linux/virtio_9p.h
 create mode 100644 include/linux/virtio_balloon.h
 create mode 100644 include/linux/virtio_blk.h
 create mode 100644 include/linux/virtio_config.h
 create mode 100644 include/linux/virtio_console.h
 create mode 100644 include/linux/virtio_pci.h
 create mode 100644 include/linux/virtio_ring.h
 create mode 100644 include/linux/virtio_rng.h

-- 
2.25.1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 kvmtool 02/12] builtin-run: Always use RAM size in bytes

2022-05-23 Thread Andre Przywara
On Mon, 16 May 2022 16:55:16 +0100
Alexandru Elisei  wrote:

> The user can specify the virtual machine memory size in MB, which is saved
> in cfg->ram_size. kvmtool validates it against the host memory size,
> converted from bytes to MB. ram_size is then converted to bytes, and this
> is how it is used throughout the rest of kvmtool.
> 
> To avoid any confusion about the unit of measurement, especially once the
> user is allowed to specify the unit of measurement, always use ram_size in
> bytes.
> 
> Signed-off-by: Alexandru Elisei 
> ---
>  builtin-run.c| 19 ++-
>  include/kvm/kvm-config.h |  7 ---
>  include/kvm/kvm.h|  2 +-
>  3 files changed, 15 insertions(+), 13 deletions(-)
> 
> diff --git a/builtin-run.c b/builtin-run.c
> index 0126c9fbcba6..236c59d2f86f 100644
> --- a/builtin-run.c
> +++ b/builtin-run.c
> @@ -36,6 +36,7 @@
>  
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  #include 
> @@ -264,7 +265,7 @@ static u64 host_ram_size(void)
>   return 0;
>   }
>  
> - return (nr_pages * page_size) >> MB_SHIFT;
> + return nr_pages * page_size;

So while looking for potential overflows on 32-bit systems, I realised
that this was already broken: On my Calxeda Highbank (arm32) with 8GB of
memory, this returns a negative number, because of the signed longs.
Can you cast nr_pages to u64 while at it, to fix that? I don't think we
need a separate patch for that ...

>  }
>  
>  /*
> @@ -278,11 +279,11 @@ static u64 get_ram_size(int nr_cpus)
>   u64 available;
>   u64 ram_size;
>  
> - ram_size= 64 * (nr_cpus + 3);
> + ram_size= SZ_64M * (nr_cpus + 3);

This overflows on 32-bit system starting with 29 vCPUs. If you use "3ULL",
this problem goes away.

Cheers,
Andre

>  
>   available   = host_ram_size() * RAM_SIZE_RATIO;
>   if (!available)
> - available = MIN_RAM_SIZE_MB;
> + available = MIN_RAM_SIZE;
>  
>   if (ram_size > available)
>   ram_size= available;
> @@ -595,13 +596,13 @@ static struct kvm *kvm_cmd_run_init(int argc, const 
> char **argv)
>  
>   if (!kvm->cfg.ram_size)
>   kvm->cfg.ram_size = get_ram_size(kvm->cfg.nrcpus);
> + else
> + kvm->cfg.ram_size <<= MB_SHIFT;
>  
>   if (kvm->cfg.ram_size > host_ram_size())
>   pr_warning("Guest memory size %lluMB exceeds host physical RAM 
> size %lluMB",
> - (unsigned long long)kvm->cfg.ram_size,
> - (unsigned long long)host_ram_size());
> -
> - kvm->cfg.ram_size <<= MB_SHIFT;
> + (unsigned long long)kvm->cfg.ram_size >> MB_SHIFT,
> + (unsigned long long)host_ram_size() >> MB_SHIFT);
>  
>   if (!kvm->cfg.dev)
>   kvm->cfg.dev = DEFAULT_KVM_DEV;
> @@ -676,12 +677,12 @@ static struct kvm *kvm_cmd_run_init(int argc, const 
> char **argv)
>   if (kvm->cfg.kernel_filename) {
>   printf("  # %s run -k %s -m %Lu -c %d --name %s\n", 
> KVM_BINARY_NAME,
>  kvm->cfg.kernel_filename,
> -(unsigned long long)kvm->cfg.ram_size / 1024 / 1024,
> +(unsigned long long)kvm->cfg.ram_size >> MB_SHIFT,
>  kvm->cfg.nrcpus, kvm->cfg.guest_name);
>   } else if (kvm->cfg.firmware_filename) {
>   printf("  # %s run --firmware %s -m %Lu -c %d --name %s\n", 
> KVM_BINARY_NAME,
>  kvm->cfg.firmware_filename,
> -(unsigned long long)kvm->cfg.ram_size / 1024 / 1024,
> +(unsigned long long)kvm->cfg.ram_size >> MB_SHIFT,
>  kvm->cfg.nrcpus, kvm->cfg.guest_name);
>   }
>  
> diff --git a/include/kvm/kvm-config.h b/include/kvm/kvm-config.h
> index 6a5720c4c7d4..31bc89520d52 100644
> --- a/include/kvm/kvm-config.h
> +++ b/include/kvm/kvm-config.h
> @@ -5,6 +5,8 @@
>  #include "kvm/vfio.h"
>  #include "kvm/kvm-config-arch.h"
>  
> +#include 
> +
>  #define DEFAULT_KVM_DEV  "/dev/kvm"
>  #define DEFAULT_CONSOLE  "serial"
>  #define DEFAULT_NETWORK  "user"
> @@ -15,14 +17,13 @@
>  #define DEFAULT_SCRIPT   "none"
>  #define DEFAULT_SANDBOX_FILENAME "guest/sandbox.sh"
>  
> -#define MIN_RAM_SIZE_MB  (64ULL)
> -#define MIN_RAM_SIZE_BYTE(MIN_RAM_SIZE_MB << MB_SHIFT)
> +#define MIN_RAM_SIZE SZ_64M
>  
>  struct kvm_config {
>   struct kvm_config_arch arch;
>   struct disk_image_params disk_image[MAX_DISK_IMAGES];
>   struct vfio_device_params *vfio_devices;
> - u64 ram_size;
> + u64 ram_size;   /* Guest memory size, in bytes */
>   u8 num_net_devices;
>   u8 num_vfio_devices;
>   u64 vsock_cid;
> diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
> index ad732e56f5ed..7b14b33b50ca 100644
> --- a/include/kvm/kvm.h
> +++ b/include/kvm/kvm.h
> @@ -87,7 +87,7 @@ struct kvm {
>   struct 

Re: [PATCH v2 kvmtool 12/12] arm64: Allow the user to specify the RAM base address

2022-05-20 Thread Andre Przywara
On Mon, 16 May 2022 16:55:26 +0100
Alexandru Elisei  wrote:

Hi,

> Allow the user to specify the RAM base address by using -m/--mem size@addr
> command line argument. The base address must be above 2GB, as to not
> overlap with the MMIO I/O region.

Just started to play with this, in general the series looks good to me on
a first glance. I will review in anger next week.
Meanwhile: when you start kvmtool without explicitly specifying a ram size
on the command line, the code misses to initialise cfg.ram_addr, so it
stays at 0 and kvmtool reports:
  Fatal: RAM address is below 2GB
One possible fix would be to initialise this in get_ram_size() to
kvm__arch_default_ram_address(), I guess, but you might find a better solution.

Cheers,
Andre

> 
> Signed-off-by: Alexandru Elisei 
> ---
>  arm/aarch64/include/kvm/kvm-arch.h |  2 ++
>  arm/aarch64/kvm.c  |  5 -
>  arm/kvm.c  |  7 +--
>  builtin-run.c  | 29 +
>  include/kvm/kvm-config.h   |  1 +
>  include/kvm/kvm.h  | 12 
>  6 files changed, 49 insertions(+), 7 deletions(-)
> 
> diff --git a/arm/aarch64/include/kvm/kvm-arch.h 
> b/arm/aarch64/include/kvm/kvm-arch.h
> index ff857ca6e7b4..02d09a413831 100644
> --- a/arm/aarch64/include/kvm/kvm-arch.h
> +++ b/arm/aarch64/include/kvm/kvm-arch.h
> @@ -10,6 +10,8 @@ void kvm__arch_enable_mte(struct kvm *kvm);
>  
>  #define MAX_PAGE_SIZESZ_64K
>  
> +#define ARCH_HAS_CFG_RAM_ADDRESS 1
> +
>  #include "arm-common/kvm-arch.h"
>  
>  #endif /* KVM__KVM_ARCH_H */
> diff --git a/arm/aarch64/kvm.c b/arm/aarch64/kvm.c
> index af8e7eae0da2..14ffae9e39dc 100644
> --- a/arm/aarch64/kvm.c
> +++ b/arm/aarch64/kvm.c
> @@ -44,6 +44,9 @@ void kvm__arch_validate_cfg(struct kvm *kvm)
>   die("RAM size 0x%llx exceeds maximum allowed 0x%llx",
>   kvm->cfg.ram_size, ARM_LOMAP_MAX_MEMORY);
>   }
> +
> + if (kvm->cfg.ram_addr < ARM_MEMORY_AREA)
> + die("RAM address is below %luGB", ARM_MEMORY_AREA >> 30);
>  }
>  
>  u64 kvm__arch_default_ram_address(void)
> @@ -117,7 +120,7 @@ int kvm__get_vm_type(struct kvm *kvm)
>   return 0;
>  
>   /* Otherwise, compute the minimal required IPA size */
> - max_ipa = ARM_MEMORY_AREA + kvm->cfg.ram_size - 1;
> + max_ipa = kvm->cfg.ram_addr + kvm->cfg.ram_size - 1;
>   ipa_bits = max(32, fls_long(max_ipa));
>   pr_debug("max_ipa %lx ipa_bits %d max_ipa_bits %d",
>max_ipa, ipa_bits, max_ipa_bits);
> diff --git a/arm/kvm.c b/arm/kvm.c
> index abcccfabf59e..d51cc15d8b1c 100644
> --- a/arm/kvm.c
> +++ b/arm/kvm.c
> @@ -55,7 +55,7 @@ void kvm__init_ram(struct kvm *kvm)
>   madvise(kvm->arch.ram_alloc_start, kvm->arch.ram_alloc_size,
>   MADV_HUGEPAGE);
>  
> - phys_start  = ARM_MEMORY_AREA;
> + phys_start  = kvm->cfg.ram_addr;
>   phys_size   = kvm->ram_size;
>   host_mem= kvm->ram_start;
>  
> @@ -65,6 +65,9 @@ void kvm__init_ram(struct kvm *kvm)
>   "address 0x%llx [err %d]", phys_size, phys_start, err);
>  
>   kvm->arch.memory_guest_start = phys_start;
> +
> + pr_debug("RAM created at 0x%llx - 0x%llx",
> +  phys_start, phys_start + phys_size - 1);
>  }
>  
>  void kvm__arch_delete_ram(struct kvm *kvm)
> @@ -201,7 +204,7 @@ bool kvm__load_firmware(struct kvm *kvm, const char 
> *firmware_filename)
>  
>   /* For default firmware address, lets load it at the begining of RAM */
>   if (fw_addr == 0)
> - fw_addr = ARM_MEMORY_AREA;
> + fw_addr = kvm->arch.memory_guest_start;
>  
>   if (!validate_fw_addr(kvm, fw_addr))
>   die("Bad firmware destination: 0x%016llx", fw_addr);
> diff --git a/builtin-run.c b/builtin-run.c
> index 57c58be55159..26e6e9974009 100644
> --- a/builtin-run.c
> +++ b/builtin-run.c
> @@ -131,12 +131,22 @@ static u64 parse_mem_option(const char *nptr, char 
> **next)
>  static int mem_parser(const struct option *opt, const char *arg, int unset)
>  {
>   struct kvm *kvm = opt->ptr;
> - char *next;
> + char *next, *nptr;
>  
>   kvm->cfg.ram_size = parse_mem_option(arg, );
>   if (kvm->cfg.ram_size == 0)
>   die("Invalid RAM size: %s", arg);
>  
> + kvm->cfg.ram_addr = kvm__arch_default_ram_address();
> + if (kvm__arch_has_cfg_ram_address() && *next == '@') {
> + next++;
> + if (*next == '\0')
> + die("Missing memory address: %s", arg);
> +
> + nptr = next;
> + kvm->cfg.ram_addr = parse_mem_option(nptr, );
> + }
> +
>   if (*next != '\0')
>   die("Invalid memory specifier: %s", arg);
>  
> @@ -147,15 +157,26 @@ static int mem_parser(const struct option *opt, const 
> char *arg, int unset)
>  #define OPT_ARCH_RUN(...)
>  #endif
>  
> +#ifdef ARCH_HAS_CFG_RAM_ADDRESS
> +#define MEM_OPT_HELP_SHORT   

Re: [PATCH kvmtool v3] aarch64: Add stolen time support

2022-02-22 Thread Andre Przywara
On Tue, 22 Feb 2022 14:50:56 +
Alexandru Elisei  wrote:

> Hi,
> 
> On Tue, Feb 22, 2022 at 02:35:24PM +, Marc Zyngier wrote:
> > On 2022-02-22 14:28, Alexandru Elisei wrote:  
> > > Hi,
> > > 
> > > On Tue, Feb 22, 2022 at 02:18:40PM +, Marc Zyngier wrote:  
> > > > On 2022-02-22 13:58, Alexandru Elisei wrote:  
> > > > > Hi,
> > > > >
> > > > > On Tue, Feb 22, 2022 at 10:08:30AM +, Sebastian Ene wrote:  
> > > > > > This patch adds support for stolen time by sharing a memory region
> > > > > > with the guest which will be used by the hypervisor to store the
> > > > > > stolen
> > > > > > time information. The exact format of the structure stored by the
> > > > > > hypervisor is described in the ARM DEN0057A document.
> > > > > >
> > > > > > Signed-off-by: Sebastian Ene 
> > > > > > ---
> > > > > >  Changelog since v2:
> > > > > >  - Moved the AARCH64_PVTIME_* definitions from arm-common/kvm-arch.h
> > > > > > to
> > > > > >arm64/pvtime.c as pvtime is only available for arm64.
> > > > > >
> > > > > >  Changelog since v1:
> > > > > >  - Removed the pvtime.h header file and moved the definitions to
> > > > > > kvm-cpu-arch.h
> > > > > >Verified if the stolen time capability is supported before
> > > > > > allocating
> > > > > >and mapping the memory.
> > > > > >
> > > > > >  Makefile   |  1 +
> > > > > >  arm/aarch64/arm-cpu.c  |  1 +
> > > > > >  arm/aarch64/include/kvm/kvm-cpu-arch.h |  1 +
> > > > > >  arm/aarch64/pvtime.c   | 89
> > > > > > ++
> > > > > >  arm/kvm-cpu.c  | 14 ++--
> > > > > >  5 files changed, 99 insertions(+), 7 deletions(-)
> > > > > >  create mode 100644 arm/aarch64/pvtime.c
> > > > > >
> > > > > > diff --git a/Makefile b/Makefile
> > > > > > index f251147..e9121dc 100644
> > > > > > --- a/Makefile
> > > > > > +++ b/Makefile
> > > > > > @@ -182,6 +182,7 @@ ifeq ($(ARCH), arm64)
> > > > > > OBJS+= arm/aarch64/arm-cpu.o
> > > > > > OBJS+= arm/aarch64/kvm-cpu.o
> > > > > > OBJS+= arm/aarch64/kvm.o
> > > > > > +   OBJS+= arm/aarch64/pvtime.o
> > > > > > ARCH_INCLUDE:= $(HDRS_ARM_COMMON)
> > > > > > ARCH_INCLUDE+= -Iarm/aarch64/include
> > > > > >
> > > > > > diff --git a/arm/aarch64/arm-cpu.c b/arm/aarch64/arm-cpu.c
> > > > > > index d7572b7..326fb20 100644
> > > > > > --- a/arm/aarch64/arm-cpu.c
> > > > > > +++ b/arm/aarch64/arm-cpu.c
> > > > > > @@ -22,6 +22,7 @@ static void generate_fdt_nodes(void *fdt, struct
> > > > > > kvm *kvm)
> > > > > >  static int arm_cpu__vcpu_init(struct kvm_cpu *vcpu)
> > > > > >  {
> > > > > > vcpu->generate_fdt_nodes = generate_fdt_nodes;
> > > > > > +   kvm_cpu__setup_pvtime(vcpu);
> > > > > > return 0;
> > > > > >  }
> > > > > >
> > > > > > diff --git a/arm/aarch64/include/kvm/kvm-cpu-arch.h
> > > > > > b/arm/aarch64/include/kvm/kvm-cpu-arch.h
> > > > > > index 8dfb82e..b57d6e6 100644
> > > > > > --- a/arm/aarch64/include/kvm/kvm-cpu-arch.h
> > > > > > +++ b/arm/aarch64/include/kvm/kvm-cpu-arch.h
> > > > > > @@ -19,5 +19,6 @@
> > > > > >
> > > > > >  void kvm_cpu__select_features(struct kvm *kvm, struct kvm_vcpu_init
> > > > > > *init);
> > > > > >  int kvm_cpu__configure_features(struct kvm_cpu *vcpu);
> > > > > > +void kvm_cpu__setup_pvtime(struct kvm_cpu *vcpu);
> > > > > >
> > > > > >  #endif /* KVM__KVM_CPU_ARCH_H */
> > > > > > diff --git a/arm/aarch64/pvtime.c b/arm/aarch64/pvtime.c
> > > > > > new file mode 100644
> > > > > > index 000..247e4f3
> > > > > > --- /dev/null
> > > > > > +++ b/arm/aarch64/pvtime.c
> > > > > > @@ -0,0 +1,89 @@
> > > > > > +#include "kvm/kvm.h"
> > > > > > +#include "kvm/kvm-cpu.h"
> > > > > > +#include "kvm/util.h"
> > > > > > +
> > > > > > +#include 
> > > > > > +#include 
> > > > > > +
> > > > > > +#define AARCH64_PVTIME_IPA_MAX_SIZESZ_64K
> > > > > > +#define AARCH64_PVTIME_IPA_START   (ARM_MEMORY_AREA - \
> > > > > > +AARCH64_PVTIME_IPA_MAX_SIZE)  
> > > > >
> > > > > This doesn't change the fact that it overlaps with KVM_PCI_MMIO_AREA,
> > > > > which is
> > > > > exposed to the guest in the DTB (see my reply to v2).  
> > > > 
> > > > Yup, this is a bit of a problem, and overlapping regions are
> > > > a big no-no. Why can't the pvtime region be dynamically placed
> > > > after the RAM (after checking that there is enough space to
> > > > register it in the IPA space)?  
> > > 
> > > In theory, is there something to stop someone from creating a VM with
> > > enough
> > > memory to reach the end of the IPA space?  
> > 
> > No, but we can either steal 64kB from that upper limit if that's the
> > case, or let the user know that stolen time is disabled because they
> > have been greedy...  
> 
> If we decide to go with having the pvtime region after RAM, I would prefer to
> disable it if there's no room, and print a big warning letting the user know
> 

Re: [PATCH][kvmtool] virtio/pci: Size the MSI-X bar according to the number of MSI-X

2021-08-31 Thread Andre Przywara
On Tue, 31 Aug 2021 12:28:28 +0100
Marc Zyngier  wrote:

> Hi Andre,
> 
> On Tue, 31 Aug 2021 12:10:35 +0100,
> Andre Przywara  wrote:
> > 
> > On Fri, 27 Aug 2021 12:54:05 +0100
> > Marc Zyngier  wrote:
> > 
> > Hi Marc,
> >   
> > > Since 45d3b59e8c45 ("kvm tools: Increase amount of possible interrupts
> > > per PCI device"), the number of MSI-S has gone from 4 to 33.
> > > 
> > > However, the corresponding storage hasn't been upgraded, and writing
> > > to the MSI-X table is a pretty risky business. Now that the Linux
> > > kernel writes to *all* MSI-X entries before doing anything else
> > > with the device, kvmtool dies a horrible death.
> > > 
> > > Fix it by properly defining the size of the MSI-X bar, and make
> > > Linux great again.
> > > 
> > > This includes some fixes the PBA region decoding, as well as minor
> > > cleanups to make this code a bit more maintainable.
> > > 
> > > Signed-off-by: Marc Zyngier   
> > 
> > Many thanks for fixing this, it looks good to me now. Just some
> > questions below:

Thanks for the explanation, and keeping (void *) as there are more
instances sounds fair enough. So:

Reviewed-by: Andre Przywara 

Cheers,
Andre


> >   
> > > ---
> > >  virtio/pci.c | 42 ++
> > >  1 file changed, 30 insertions(+), 12 deletions(-)
> > > 
> > > diff --git a/virtio/pci.c b/virtio/pci.c
> > > index eb91f512..41085291 100644
> > > --- a/virtio/pci.c
> > > +++ b/virtio/pci.c
> > > @@ -7,6 +7,7 @@
> > >  #include "kvm/irq.h"
> > >  #include "kvm/virtio.h"
> > >  #include "kvm/ioeventfd.h"
> > > +#include "kvm/util.h"
> > >  
> > >  #include 
> > >  #include 
> > > @@ -14,6 +15,13 @@
> > >  #include 
> > >  #include 
> > >  
> > > +#define ALIGN_UP(x, s)   ALIGN((x) + (s) - 1, (s))
> > > +#define VIRTIO_NR_MSIX   (VIRTIO_PCI_MAX_VQ + 
> > > VIRTIO_PCI_MAX_CONFIG)
> > > +#define VIRTIO_MSIX_TABLE_SIZE   (VIRTIO_NR_MSIX * 16)
> > > +#define VIRTIO_MSIX_PBA_SIZE (ALIGN_UP(VIRTIO_MSIX_TABLE_SIZE, 64) / 
> > > 8)
> > > +#define VIRTIO_MSIX_BAR_SIZE (1UL << fls_long(VIRTIO_MSIX_TABLE_SIZE 
> > > + \
> > > +  VIRTIO_MSIX_PBA_SIZE))
> > > +
> > >  static u16 virtio_pci__port_addr(struct virtio_pci *vpci)
> > >  {
> > >   return pci__bar_address(>pci_hdr, 0);
> > > @@ -333,18 +341,27 @@ static void virtio_pci__msix_mmio_callback(struct 
> > > kvm_cpu *vcpu,
> > >   struct virtio_pci *vpci = vdev->virtio;
> > >   struct msix_table *table;
> > >   u32 msix_io_addr = virtio_pci__msix_io_addr(vpci);
> > > + u32 pba_offset;
> > >   int vecnum;
> > >   size_t offset;
> > >  
> > > - if (addr > msix_io_addr + PCI_IO_SIZE) {  
> > 
> > Ouch, the missing "=" looks like another long standing bug you fixed, I
> > wonder how this ever worked before? Looking deeper it looks like the
> > whole PBA code was quite broken (allowing writes, for instance, and
> > mixing with the code for the MSIX table)?  
> 
> I don't think it ever worked. And to be fair, no known guest ever
> reads from it either. It just that as I was reworking it, some of the
> pitfalls became obvious.
> 
> >   
> > > + BUILD_BUG_ON(VIRTIO_NR_MSIX > (sizeof(vpci->msix_pba) * 8));
> > > +
> > > + pba_offset = vpci->pci_hdr.msix.pba_offset & ~PCI_MSIX_TABLE_BIR;  
> > 
> > Any particular reason you read back the offset from the MSIX capability
> > instead of just using VIRTIO_MSIX_TABLE_SIZE here? Is that to avoid
> > accidentally diverging in the future, by having just one place of
> > definition?  
> 
> Exactly. My first version of this patch actually failed to update the
> offset advertised to the guest, so I decided to just have a single
> location for this. At least, we won't have to touch this code again if
> we change the number of MSI-X.
> 
> >   
> > > + if (addr >= msix_io_addr + pba_offset) {
> > > + /* Read access to PBA */
> > >   if (is_write)
> > >   return;
> > > - table  = (struct msix_table *)>msix_pba;
> > > - offset = addr - (msix_io_addr + PCI_IO_SIZE);
> > > - } else {
> > > - table  = vpci->msix_table;
> > > - offset = addr - msix_io_addr;
> > > + offset = addr - (msix_io_addr + pba_offset);
> > > + if ((offset + len) > sizeof (vpci->msix_pba))
> > > + return;
> > > + memcpy(data, (void *)>msix_pba + offset, len);  
> > 
> > Should this be a char* cast, since pointer arithmetic on void* is
> > somewhat frowned upon (aka "forbidden in the C standard, but allowed as
> > a GCC extension")?  
> 
> I am trying to be consistent. A quick grep shows at least 19
> occurrences of pointer arithmetic with '(void *)', and none with
> '(char *)'. Happy for someone to go and repaint this, but I don't
> think this should be the purpose of this patch.
> 
> Thanks,
> 
>   M.
> 

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH][kvmtool] virtio/pci: Size the MSI-X bar according to the number of MSI-X

2021-08-31 Thread Andre Przywara
On Fri, 27 Aug 2021 12:54:05 +0100
Marc Zyngier  wrote:

Hi Marc,

> Since 45d3b59e8c45 ("kvm tools: Increase amount of possible interrupts
> per PCI device"), the number of MSI-S has gone from 4 to 33.
> 
> However, the corresponding storage hasn't been upgraded, and writing
> to the MSI-X table is a pretty risky business. Now that the Linux
> kernel writes to *all* MSI-X entries before doing anything else
> with the device, kvmtool dies a horrible death.
> 
> Fix it by properly defining the size of the MSI-X bar, and make
> Linux great again.
> 
> This includes some fixes the PBA region decoding, as well as minor
> cleanups to make this code a bit more maintainable.
> 
> Signed-off-by: Marc Zyngier 

Many thanks for fixing this, it looks good to me now. Just some
questions below:

> ---
>  virtio/pci.c | 42 ++
>  1 file changed, 30 insertions(+), 12 deletions(-)
> 
> diff --git a/virtio/pci.c b/virtio/pci.c
> index eb91f512..41085291 100644
> --- a/virtio/pci.c
> +++ b/virtio/pci.c
> @@ -7,6 +7,7 @@
>  #include "kvm/irq.h"
>  #include "kvm/virtio.h"
>  #include "kvm/ioeventfd.h"
> +#include "kvm/util.h"
>  
>  #include 
>  #include 
> @@ -14,6 +15,13 @@
>  #include 
>  #include 
>  
> +#define ALIGN_UP(x, s)   ALIGN((x) + (s) - 1, (s))
> +#define VIRTIO_NR_MSIX   (VIRTIO_PCI_MAX_VQ + 
> VIRTIO_PCI_MAX_CONFIG)
> +#define VIRTIO_MSIX_TABLE_SIZE   (VIRTIO_NR_MSIX * 16)
> +#define VIRTIO_MSIX_PBA_SIZE (ALIGN_UP(VIRTIO_MSIX_TABLE_SIZE, 64) / 8)
> +#define VIRTIO_MSIX_BAR_SIZE (1UL << fls_long(VIRTIO_MSIX_TABLE_SIZE + \
> +  VIRTIO_MSIX_PBA_SIZE))
> +
>  static u16 virtio_pci__port_addr(struct virtio_pci *vpci)
>  {
>   return pci__bar_address(>pci_hdr, 0);
> @@ -333,18 +341,27 @@ static void virtio_pci__msix_mmio_callback(struct 
> kvm_cpu *vcpu,
>   struct virtio_pci *vpci = vdev->virtio;
>   struct msix_table *table;
>   u32 msix_io_addr = virtio_pci__msix_io_addr(vpci);
> + u32 pba_offset;
>   int vecnum;
>   size_t offset;
>  
> - if (addr > msix_io_addr + PCI_IO_SIZE) {

Ouch, the missing "=" looks like another long standing bug you fixed, I
wonder how this ever worked before? Looking deeper it looks like the
whole PBA code was quite broken (allowing writes, for instance, and
mixing with the code for the MSIX table)?

> + BUILD_BUG_ON(VIRTIO_NR_MSIX > (sizeof(vpci->msix_pba) * 8));
> +
> + pba_offset = vpci->pci_hdr.msix.pba_offset & ~PCI_MSIX_TABLE_BIR;

Any particular reason you read back the offset from the MSIX capability
instead of just using VIRTIO_MSIX_TABLE_SIZE here? Is that to avoid
accidentally diverging in the future, by having just one place of
definition?

> + if (addr >= msix_io_addr + pba_offset) {
> + /* Read access to PBA */
>   if (is_write)
>   return;
> - table  = (struct msix_table *)>msix_pba;
> - offset = addr - (msix_io_addr + PCI_IO_SIZE);
> - } else {
> - table  = vpci->msix_table;
> - offset = addr - msix_io_addr;
> + offset = addr - (msix_io_addr + pba_offset);
> + if ((offset + len) > sizeof (vpci->msix_pba))
> + return;
> + memcpy(data, (void *)>msix_pba + offset, len);

Should this be a char* cast, since pointer arithmetic on void* is
somewhat frowned upon (aka "forbidden in the C standard, but allowed as
a GCC extension")?

Cheers,
Andre

> + return;
>   }
> +
> + table  = vpci->msix_table;
> + offset = addr - msix_io_addr;
> +
>   vecnum = offset / sizeof(struct msix_table);
>   offset = offset % sizeof(struct msix_table);
>  
> @@ -520,7 +537,7 @@ int virtio_pci__init(struct kvm *kvm, void *dev, struct 
> virtio_device *vdev,
>  
>   port_addr = pci_get_io_port_block(PCI_IO_SIZE);
>   mmio_addr = pci_get_mmio_block(PCI_IO_SIZE);
> - msix_io_block = pci_get_mmio_block(PCI_IO_SIZE * 2);
> + msix_io_block = pci_get_mmio_block(VIRTIO_MSIX_BAR_SIZE);
>  
>   vpci->pci_hdr = (struct pci_device_header) {
>   .vendor_id  = 
> cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
> @@ -543,7 +560,7 @@ int virtio_pci__init(struct kvm *kvm, void *dev, struct 
> virtio_device *vdev,
>   .capabilities   = (void *)>pci_hdr.msix - (void 
> *)>pci_hdr,
>   .bar_size[0]= cpu_to_le32(PCI_IO_SIZE),
>   .bar_size[1]= cpu_to_le32(PCI_IO_SIZE),
> - .bar_size[2]= cpu_to_le32(PCI_IO_SIZE*2),
> + .bar_size[2]= cpu_to_le32(VIRTIO_MSIX_BAR_SIZE),
>   };
>  
>   r = pci__register_bar_regions(kvm, >pci_hdr,
> @@ -560,8 +577,9 @@ int virtio_pci__init(struct kvm *kvm, void *dev, struct 
> virtio_device *vdev,
>   vpci->pci_hdr.msix.cap = PCI_CAP_ID_MSIX;
>   vpci->pci_hdr.msix.next = 0;
>   /*
> -   

Re: [PATCH][kvmtool] virtio/pci: Correctly handle MSI-X masking while MSI-X is disabled

2021-08-26 Thread Andre Przywara

On 8/25/21 6:44 PM, Marc Zyngier wrote:

Hi Marc,


On Wed, 25 Aug 2021 16:33:21 +0100,
Marc Zyngier  wrote:


On Tue, 24 Aug 2021 15:32:53 +0100,
Marc Zyngier  wrote:


Hi Andre,

On Mon, 23 Aug 2021 17:48:33 +0100,
Andre Przywara  wrote:


On Sat, 21 Aug 2021 13:07:42 +0100
Marc Zyngier  wrote:

Hi Marc,


Since Linux commit 7d5ec3d36123 ("PCI/MSI: Mask all unused MSI-X
entries"), kvmtool segfaults when the guest boots and tries to
disable all the MSI-X entries of a virtio device while MSI-X itself
is disabled.

What Linux does is seems perfectly correct. However, kvmtool uses
a different decoding depending on whether MSI-X is enabled for
this device or not. Which seems pretty wrong.


While I really wish this would be wrong, I think this is
indeed how this is supposed to work: The Virtio legacy spec makes the
existence of those two virtio config fields dependent on the
(dynamic!) enablement status of MSI-X. This is reflected in:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/virtio_pci.h#n72
and explicitly mentioned as a footnote in the virtio 0.9.5 spec[1]:
"3) ie. once you enable MSI-X on the device, the other fields move. If
you turn it off again, they move back!"


Madness! What was Rusty on at the time? I really hope the bitcoin
thing is buying him better stuff...


I agree that this looks like a bad idea, but I am afraid we are stuck
with this. It looks like the Linux driver is at fault here, it should
not issue the config access when MSIs are disabled. Something like this
(untested):

--- a/drivers/virtio/virtio_pci_legacy.c
+++ b/drivers/virtio/virtio_pci_legacy.c
@@ -103,6 +103,9 @@ static void vp_reset(struct virtio_device *vdev)
  
  static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)

  {
+   if (!vp_dev->msix_enabled)
+   return VIRTIO_MSI_NO_VECTOR;
+
 /* Setup the vector used for configuration events */
 iowrite16(vector, vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
 /* Verify we had enough resources to assign the vector */

This is just my first idea after looking at this, happy to stand
corrected or hear about a better solution.


I don't think this works. It instead completely disables MSI-X, which
is a total bore. I think the only way to deal with it is to quirk it
to prevent the bulk masking to take effect before MSI-X is enabled.


Actually, let me correct myself. I tested the wrong configuration (why
isn't --force-pci the bloody default in kvmtool?).


I guess because there is no --force-mmio, and PCI on ARM was kind of 
daunting back then ;-)




This patch doesn't
fix anything at all, and kvmtool just explodes.

Having dug further, it isn't the config space that causes problems,
but the programming of the MSI-X vectors. I'm starting to suspect the
layout of the MSI-X bar in kvmtool.


OK, this is hilarious. Sort of. The MSI-X bar sizing is bonkers: you
can't fit 33 MSIs there (33 being the number of MSI-X that kvmtool
advertises), and you will have notionally overwritten the PBA as
well. Amusingly, the last write ends up being misdecoded as a config
space access...


Ah, very good find indeed, many thanks for the debugging!

I am only halfway through the code by now, but wouldn't you need to 
adjust the PBA offset in the MSIX capability as well? This is still 
stuck at that (misnamed) PCI_IO_SIZE, in 
virtio/pci.c:virtio_pci__init(): vpci->pci_hdr.msix.pba_offset =

And IIUC this has to match the decoding in virtio_pci__msix_mmio_callback().

Cheers,
Andre



"works for me".

M.

 From a2b3a338aab535a1683cc5b424455ed7fd3a500a Mon Sep 17 00:00:00 2001
From: Marc Zyngier 
Date: Wed, 25 Aug 2021 18:19:27 +0100
Subject: [PATCH] virtio/pci: Size the MSI-X bar according to the number of
  MSI-X

Since 45d3b59e8c45 ("kvm tools: Increase amount of possible interrupts
per PCI device"), the number of MSI-S has gone from 4 to 33.

However, the corresponding storage hasn't been upgraded, and writing
to the MSI-X table is a pretty risky business. Now that the Linux
kernel writes to *all* MSI-X entries before doing anything else
with the device, kvmtool dies a horrible death.

Fix it by properly defining the size of the MSI-X bar, and make
Linux great again.

Signed-off-by: Marc Zyngier 
---
  virtio/pci.c | 29 +
  1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/virtio/pci.c b/virtio/pci.c
index eb91f512..726146fc 100644
--- a/virtio/pci.c
+++ b/virtio/pci.c
@@ -7,6 +7,7 @@
  #include "kvm/irq.h"
  #include "kvm/virtio.h"
  #include "kvm/ioeventfd.h"
+#include "kvm/util.h"
  
  #include 

  #include 
@@ -14,6 +15,13 @@
  #include 
  #include 
  
+#define ALIGN_UP(x, s)		ALIGN((x) + (s) - 1, (s))

+#define VIRTIO_NR_MSIX (VIRTIO_PCI_MAX_VQ + VIRTIO_PCI_MAX_CONFIG)
+#define VIRTIO_MSIX_TABLE_SIZE (VIRTIO_NR_MSIX * 16)
+#define VIRTIO_MSIX_P

Re: [PATCH v2 3/3] kvmtool: arm64: Configure VM with the minimal required IPA space

2021-08-23 Thread Andre Przywara
On Sun, 22 Aug 2021 16:25:26 +0100
Marc Zyngier  wrote:

Hi Marc,

> There is some value in keeping the IPA space small, as it reduces
> the size of the stage-2 page tables.
> 
> Let's compute the required space at VM creation time, and inform
> the kernel of our requirements.

You mentioned some kernel bug in the first version of this patch, I
guess the fix for this is 262b003d059c?
It seems to me that this is somewhat of a regression on older host
kernels, when trying to run a guest with "-m 2048", for instance?
Should we teach kvmtool about this bug, and do a check for the bug
condition, when kvm__register_ram() returns with -EFAULT? And give users
a hint to try with one MB more or less guest RAM? Or maybe try
this automatically?

> 
> Signed-off-by: Marc Zyngier 
> ---
>  arm/aarch64/kvm.c | 20 +++-
>  1 file changed, 19 insertions(+), 1 deletion(-)
> 
> diff --git a/arm/aarch64/kvm.c b/arm/aarch64/kvm.c
> index d03a27f2..4e66a22e 100644
> --- a/arm/aarch64/kvm.c
> +++ b/arm/aarch64/kvm.c
> @@ -3,6 +3,7 @@
>  #include 
>  
>  #include 
> +#include 
>  
>  /*
>   * Return the TEXT_OFFSET value that the guest kernel expects. Note
> @@ -59,5 +60,22 @@ int kvm__arch_get_ipa_limit(struct kvm *kvm)
>  
>  int kvm__get_vm_type(struct kvm *kvm)
>  {
> - return KVM_VM_TYPE_ARM_IPA_SIZE(kvm__arch_get_ipa_limit(kvm));
> + unsigned int ipa_bits, max_ipa_bits;
> + unsigned long max_ipa;
> +
> + /* If we're running on an old kernel, use 0 as the VM type */
> + max_ipa_bits = kvm__arch_get_ipa_limit(kvm);
> + if (!max_ipa_bits)
> + return 0;

Should this return KVM_VM_TYPE, as it does at the moment? Or is this
more confusing than helpful?

Just a nit anyway, the patch looks correct otherwise:

Reviewed-by: Andre Przywara 

Cheers,
Andre

> +
> + /* Otherwise, compute the minimal required IPA size */
> + max_ipa = ARM_MEMORY_AREA + kvm->cfg.ram_size - 1;
> + ipa_bits = max(32, fls_long(max_ipa));
> + pr_debug("max_ipa %lx ipa_bits %d max_ipa_bits %d",
> +  max_ipa, ipa_bits, max_ipa_bits);
> +
> + if (ipa_bits > max_ipa_bits)
> + die("Memory too large for this system (needs %d bits, %d 
> available)", ipa_bits, max_ipa_bits);
> +
> + return KVM_VM_TYPE_ARM_IPA_SIZE(ipa_bits);
>  }

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 2/3] kvmtool: arm64: Use the maximum supported IPA size when creating the VM

2021-08-23 Thread Andre Przywara
On Sun, 22 Aug 2021 16:25:25 +0100
Marc Zyngier  wrote:

Hi Marc,

> Instead of just asking the the default VM size, request the maximum
> IPA size to the kernel, and use this at VM creation time.
> 
> The IPA space is parametrized accordingly.

Thanks for the change!

> Signed-off-by: Marc Zyngier 

Reviewed-by: Andre Przywara 

Cheers,
Andre

> ---
>  arm/aarch64/include/kvm/kvm-arch.h | 19 ---
>  arm/aarch64/kvm.c  | 15 +++
>  2 files changed, 31 insertions(+), 3 deletions(-)
> 
> diff --git a/arm/aarch64/include/kvm/kvm-arch.h 
> b/arm/aarch64/include/kvm/kvm-arch.h
> index 55ef8ed1..159567b9 100644
> --- a/arm/aarch64/include/kvm/kvm-arch.h
> +++ b/arm/aarch64/include/kvm/kvm-arch.h
> @@ -3,10 +3,23 @@
>  
>  struct kvm;
>  unsigned long long kvm__arch_get_kern_offset(struct kvm *kvm, int fd);
> +int kvm__arch_get_ipa_limit(struct kvm *kvm);
>  
> -#define ARM_MAX_MEMORY(kvm)  ((kvm)->cfg.arch.aarch32_guest  ?   \
> - ARM_LOMAP_MAX_MEMORY:   \
> - ARM_HIMAP_MAX_MEMORY)
> +#define ARM_MAX_MEMORY(kvm)  ({  \
> + u64 max_ram;\
> + \
> + if ((kvm)->cfg.arch.aarch32_guest) {\
> + max_ram = ARM_LOMAP_MAX_MEMORY; \
> + } else {\
> + int ipabits = kvm__arch_get_ipa_limit(kvm); \
> + if (ipabits <= 0)   \
> + max_ram = ARM_HIMAP_MAX_MEMORY; \
> + else\
> + max_ram = (1ULL << ipabits) - ARM_MEMORY_AREA;  \
> + }   \
> + \
> + max_ram;\
> +})
>  
>  #include "arm-common/kvm-arch.h"
>  
> diff --git a/arm/aarch64/kvm.c b/arm/aarch64/kvm.c
> index 49e1dd31..d03a27f2 100644
> --- a/arm/aarch64/kvm.c
> +++ b/arm/aarch64/kvm.c
> @@ -46,3 +46,18 @@ fail:
>   return 0x8;
>  }
>  
> +int kvm__arch_get_ipa_limit(struct kvm *kvm)
> +{
> + int ret;
> +
> + ret = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_ARM_VM_IPA_SIZE);
> + if (ret <= 0)
> + ret = 0;
> +
> + return ret;
> +}
> +
> +int kvm__get_vm_type(struct kvm *kvm)
> +{
> + return KVM_VM_TYPE_ARM_IPA_SIZE(kvm__arch_get_ipa_limit(kvm));
> +}

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH][kvmtool] virtio/pci: Correctly handle MSI-X masking while MSI-X is disabled

2021-08-23 Thread Andre Przywara
On Sat, 21 Aug 2021 13:07:42 +0100
Marc Zyngier  wrote:

Hi Marc,

> Since Linux commit 7d5ec3d36123 ("PCI/MSI: Mask all unused MSI-X
> entries"), kvmtool segfaults when the guest boots and tries to
> disable all the MSI-X entries of a virtio device while MSI-X itself
> is disabled.
> 
> What Linux does is seems perfectly correct. However, kvmtool uses
> a different decoding depending on whether MSI-X is enabled for
> this device or not. Which seems pretty wrong.

While I really wish this would be wrong, I think this is
indeed how this is supposed to work: The Virtio legacy spec makes the
existence of those two virtio config fields dependent on the
(dynamic!) enablement status of MSI-X. This is reflected in:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/virtio_pci.h#n72
and explicitly mentioned as a footnote in the virtio 0.9.5 spec[1]:
"3) ie. once you enable MSI-X on the device, the other fields move. If
you turn it off again, they move back!"

I agree that this looks like a bad idea, but I am afraid we are stuck
with this. It looks like the Linux driver is at fault here, it should
not issue the config access when MSIs are disabled. Something like this
(untested):

--- a/drivers/virtio/virtio_pci_legacy.c
+++ b/drivers/virtio/virtio_pci_legacy.c
@@ -103,6 +103,9 @@ static void vp_reset(struct virtio_device *vdev)
 
 static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
 {
+   if (!vp_dev->msix_enabled)
+   return VIRTIO_MSI_NO_VECTOR;
+
/* Setup the vector used for configuration events */
iowrite16(vector, vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
/* Verify we had enough resources to assign the vector */

This is just my first idea after looking at this, happy to stand
corrected or hear about a better solution.

Cheers,
Andre

[1] https://ozlabs.org/~rusty/virtio-spec/virtio-0.9.5.pdf

> Cure the problem by removing the check against MSI-X being enabled,
> and simplify the whole logic which looked a bit odd. With this,
> Linux is back booting as a kvmtool guest with MSI-X.
> 
> Cc: Andre Przywara 
> Cc: Alexandru Elisei 
> Cc: Thomas Gleixner 
> Cc: Will Deacon 
> Signed-off-by: Marc Zyngier 
> ---
>  include/kvm/virtio.h |  2 +-
>  virtio/core.c| 12 
>  virtio/pci.c |  7 ++-
>  3 files changed, 7 insertions(+), 14 deletions(-)
> 
> diff --git a/include/kvm/virtio.h b/include/kvm/virtio.h
> index 3a311f54..7047d36f 100644
> --- a/include/kvm/virtio.h
> +++ b/include/kvm/virtio.h
> @@ -166,7 +166,7 @@ u16 virt_queue__get_head_iov(struct virt_queue *vq, 
> struct iovec iov[],
>  u16 virt_queue__get_inout_iov(struct kvm *kvm, struct virt_queue *queue,
> struct iovec in_iov[], struct iovec out_iov[],
> u16 *in, u16 *out);
> -int virtio__get_dev_specific_field(int offset, bool msix, u32 *config_off);
> +int virtio__get_dev_specific_field(int offset, u32 *config_off);
>  
>  enum virtio_trans {
>   VIRTIO_PCI,
> diff --git a/virtio/core.c b/virtio/core.c
> index 90a661d1..afb09e90 100644
> --- a/virtio/core.c
> +++ b/virtio/core.c
> @@ -169,16 +169,12 @@ void virtio_exit_vq(struct kvm *kvm, struct 
> virtio_device *vdev,
>   memset(vq, 0, sizeof(*vq));
>  }
>  
> -int virtio__get_dev_specific_field(int offset, bool msix, u32 *config_off)
> +int virtio__get_dev_specific_field(int offset, u32 *config_off)
>  {
> - if (msix) {
> - if (offset < 4)
> - return VIRTIO_PCI_O_MSIX;
> - else
> - offset -= 4;
> - }
> + if (offset < 24)
> + return VIRTIO_PCI_O_MSIX;
>  
> - *config_off = offset;
> + *config_off = offset - 24;
>  
>   return VIRTIO_PCI_O_CONFIG;
>  }
> diff --git a/virtio/pci.c b/virtio/pci.c
> index eb91f512..2a6e41f1 100644
> --- a/virtio/pci.c
> +++ b/virtio/pci.c
> @@ -112,9 +112,7 @@ static bool virtio_pci__specific_data_in(struct kvm *kvm, 
> struct virtio_device *
>  {
>   u32 config_offset;
>   struct virtio_pci *vpci = vdev->virtio;
> - int type = virtio__get_dev_specific_field(offset - 20,
> - 
> virtio_pci__msix_enabled(vpci),
> - _offset);
> + int type = virtio__get_dev_specific_field(offset, _offset);
>   if (type == VIRTIO_PCI_O_MSIX) {
>   switch (offset) {
>   case VIRTIO_MSI_CONFIG_VECTOR:
> @@ -208,8 +206,7 @@ static bool virtio_pci__specific_data_out(struct kvm 
> *kvm, struct virtio_device
>   struct virtio_pci *vpci = vdev->virtio;
>  

Re: [kvm-unit-tests RFC PATCH 3/5] run_tests.sh: Add kvmtool support

2021-07-12 Thread Andre Przywara
On Fri,  2 Jul 2021 17:31:20 +0100
Alexandru Elisei  wrote:

Hi Alex,

> Modify run_tests.sh to use kvmtool instead of qemu to run tests when
> kvm-unit-tests has been configured with --target=kvmtool.
> 
> Example invocation:
> 
> $ ./configure --target=kvmtool
> $ make clean && make
> $ ./run_scripts.sh
> 
> A custom location for the kvmtool binary can be set using the environment
> variable KVMTOOL:
> 
> $ KVMTOOL=/path/to/kvmtool/binary ./run_scripts.sh
> 
> Standalone test support is absent, but will be added in subsequent patches.

So I skimmed over this, and it's at least better than what I had tried
a few years back ;-)
And while there might be other ways to sort out command line
differences between the two, this fixup_kvmtool_opts() looks like a
clever solution to the problem.

The only problem with this patch is that it's rather big, I wonder if
this could be split up? For instance move any QEMU specific
functionality into separate functions first (like run_test_qemu()),
also use 'if [ "$TARGET" = "qemu" ]' in this first (or second?) patch.
Then later on just add the kvmtool specifics.

Cheers,
Andre

> 
> Signed-off-by: Alexandru Elisei 
> ---
>  scripts/arch-run.bash   |  48 --
>  scripts/runtime.bash|  94 --
>  scripts/mkstandalone.sh |   5 ++
>  arm/run | 110 
>  run_tests.sh|  11 +++-
>  5 files changed, 204 insertions(+), 64 deletions(-)
> 
> diff --git a/scripts/arch-run.bash b/scripts/arch-run.bash
> index 8ceed53ed7f8..b916b0e79aca 100644
> --- a/scripts/arch-run.bash
> +++ b/scripts/arch-run.bash
> @@ -69,16 +69,39 @@ run_qemu ()
>   return $ret
>  }
>  
> +run_kvmtool()
> +{
> + local stdout errors ret sig
> +
> + # kvmtool doesn't allow an initrd argument with --firmware, but 
> configure
> + # sets CONFIG_ERRATA_FORCE in lib/config.h for the kvmtool target.
> +
> + # stdout to {stdout}, stderr to $errors and stderr
> + exec {stdout}>&1
> + errors=$("${@}"  >(tee /dev/stderr) > /dev/fd/$stdout)
> + ret=$?
> + exec {stdout}>&-
> +
> + # ret=0 success, everything else is failure.
> + return $ret
> +}
> +
>  run_test_status ()
>  {
> - local stdout ret
> + local stdout ret exit_status
>  
>   exec {stdout}>&1
> - lines=$(run_qemu "$@" > >(tee /dev/fd/$stdout))
> + if [ "$TARGET" = "kvmtool" ]; then
> + lines=$(run_kvmtool "$@" > >(tee /dev/fd/$stdout))
> + exit_status=0
> + else
> + lines=$(run_qemu "$@" > >(tee /dev/fd/$stdout))
> + exit_status=1
> + fi
>   ret=$?
>   exec {stdout}>&-
>  
> - if [ $ret -eq 1 ]; then
> + if [ $ret -eq $exit_status ]; then
>   testret=$(grep '^EXIT: ' <<<"$lines" | sed 
> 's/.*STATUS=\([0-9][0-9]*\).*/\1/')
>   if [ "$testret" ]; then
>   if [ $testret -eq 1 ]; then
> @@ -193,6 +216,25 @@ search_qemu_binary ()
>   export PATH=$save_path
>  }
>  
> +search_kvmtool_binary ()
> +{
> + local lkvm kvmtool
> +
> + for lkvm in ${KVMTOOL:-lkvm vm lkvm-static}; do
> + if $lkvm --help 2>/dev/null | grep -q 'The most commonly used'; 
> then
> + kvmtool="$lkvm"
> + break
> + fi
> + done
> +
> + if [ -z "$kvmtool" ]; then
> + echo "A kvmtool binary was not found." >&2
> + echo "You can set a custom location by using the KVMTOOL= 
> environment variable." >&2
> + return 2
> + fi
> + command -v $kvmtool
> +}
> +
>  initrd_create ()
>  {
>   if [ "$ENVIRON_DEFAULT" = "yes" ]; then
> diff --git a/scripts/runtime.bash b/scripts/runtime.bash
> index 132389c7dd59..23b238a6ab6f 100644
> --- a/scripts/runtime.bash
> +++ b/scripts/runtime.bash
> @@ -12,14 +12,19 @@ extract_summary()
>  tail -3 | grep '^SUMMARY: ' | sed 's/^SUMMARY: /(/;s/'"$cr"'\{0,1\}$/)/'
>  }
>  
> -# We assume that QEMU is going to work if it tried to load the kernel
> +# We assume that QEMU/kvmtool is going to work if it tried to load the kernel
>  premature_failure()
>  {
>  local log="$(eval $(get_cmdline _NO_FILE_4Uhere_) 2>&1)"
>  
> -echo "$log" | grep "_NO_FILE_4Uhere_" |
> -grep -q -e "could not \(load\|open\) kernel" -e "error loading" &&
> -return 1
> +if [ "$TARGET" = "kvmtool" ]; then
> +echo "$log" | grep "Fatal: unable to load firmware image 
> _NO_FILE_4Uhere_" &&
> +return 1
> +else
> +echo "$log" | grep "_NO_FILE_4Uhere_" |
> +grep -q -e "could not \(load\|open\) kernel" -e "error loading" 
> &&
> +return 1
> +fi
>  
>  RUNTIME_log_stderr <<< "$log"
>  
> @@ -30,7 +35,14 @@ premature_failure()
>  get_cmdline()
>  {
>  local kernel=$1
> -echo "TESTNAME=$testname TIMEOUT=$timeout ACCEL=$accel $RUNTIME_arch_run 
> $kernel -smp $smp $opts"
> +local smp_param
> +
> 

Re: [kvm-unit-tests RFC PATCH 1/5] lib: arm: Print test exit status on exit if chr-testdev is not available

2021-07-12 Thread Andre Przywara
On Fri,  2 Jul 2021 17:31:18 +0100
Alexandru Elisei  wrote:

Hi,

> The arm64 tests can be run under kvmtool, which doesn't emulate a
> chr-testdev device. In preparation for adding run script support for
> kvmtool, print the test exit status so the scripts can pick it up and
> correctly mark the test as pass or fail.
> 
> Signed-off-by: Alexandru Elisei 
> ---
>  lib/chr-testdev.h |  1 +
>  lib/arm/io.c  | 10 +-
>  lib/chr-testdev.c |  5 +
>  3 files changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/chr-testdev.h b/lib/chr-testdev.h
> index ffd9a851aa9b..09b4b424670e 100644
> --- a/lib/chr-testdev.h
> +++ b/lib/chr-testdev.h
> @@ -11,4 +11,5 @@
>   */
>  extern void chr_testdev_init(void);
>  extern void chr_testdev_exit(int code);
> +extern bool chr_testdev_available(void);
>  #endif
> diff --git a/lib/arm/io.c b/lib/arm/io.c
> index 343e10822263..9e62b571a91b 100644
> --- a/lib/arm/io.c
> +++ b/lib/arm/io.c
> @@ -125,7 +125,15 @@ extern void halt(int code);
>  
>  void exit(int code)
>  {
> - chr_testdev_exit(code);
> + if (chr_testdev_available()) {
> + chr_testdev_exit(code);
> + } else {
> + /*
> +  * Print the test return code in the format used by chr-testdev
> +  * so the runner script can parse it.
> +  */
> + printf("\nEXIT: STATUS=%d\n", ((code) << 1) | 1);

It's more me being clueless here rather than a problem, but where does
this "EXIT: STATUS" line come from? In lib/chr-testdev.c I see "%dq",
so it this coming from QEMU (but I couldn't find it in there)?

But anyways the patch looks good and matches what PPC and s390 do.

Cheers,
Andre


> + }
>   psci_system_off();
>   halt(code);
>   __builtin_unreachable();
> diff --git a/lib/chr-testdev.c b/lib/chr-testdev.c
> index b3c641a833fe..301e73a6c064 100644
> --- a/lib/chr-testdev.c
> +++ b/lib/chr-testdev.c
> @@ -68,3 +68,8 @@ void chr_testdev_init(void)
>   in_vq = vqs[0];
>   out_vq = vqs[1];
>  }
> +
> +bool chr_testdev_available(void)
> +{
> + return vcon != NULL;
> +}

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: KVM/ARM64: Booting KVM on FVP/fastmodels

2021-06-22 Thread Andre Przywara
On Tue, 22 Jun 2021 02:33:44 +
胤桦 陈  wrote:

Hi,

> I follow the document 
> https://git.linaro.org/landing-teams/working/arm/arm-reference-platforms.git/about/docs/basefvp/user-guide.rst,

sorry for that ;-)

> and I build a Linux-on-FVP environment successfully. However, I still cannot 
> boot KVM, the details are as follows:
> 1.I make sure that two configuration files enable KVM (I guess these are the 
> right configuration files), they are
> layers/meta-arm/meta-arm-bsp/recipes-kernel/linux/files/tc0/defconfig:CONFIG_KVM=y
> build-poky/tmp-poky/work-shared/fvp-base/kernel-source/arch/arm64/configs/defconfig:CONFIG_KVM=y

> 2.I follow the document 
> https://git.linaro.org/landing-teams/working/arm/arm-reference-platforms.git/about/docs/basefvp/user-guide.rst.
>  After building the whole software stack, I try several commands but the 
> results show that KVM does not work.

Have you tried actually running a guest? Using kvmtool, for instance?
kvmtool can be statically linked, so you end up with a single
executable file, easy to copy into whatever userland you use.
If you clone it from
git://git.kernel.org/pub/scm/linux/kernel/git/will/kvmtool.git
and do "make lkvm-static" on any arm64 system, you can copy the
resulting binary "lkvm-static" into your rootfs, and then run it on the
model:
# lkvm-static run -k 
You might need to create the device file first (see below).

> The screenshots are shown as follows[commands]I try three commands,
> "kvm-ok"

This does not do much on ARM/arm64, it just merely checks for the
existence of /dev/kvm. Depending on your userland, nobody might have
created that - but still KVM might be configured fine.
A simple "mknod /dev/kvm c 10 232" fixes that, but the test passing now
doesn't mean much (as is just checks for the existence of this file,
not actual KVM functionality).

> "dmesg | grep KVM"

Please always use "grep -i" when grep'ing in dmesg, capitalisation of
those names may vary. On my kernel there is indeed not a single hit for
"KVM", but several for "kvm".
Keep in mind that this is not a bullet-proof method: the boot messages
from KVM might have been flushed from the dmesg buffer already - on one
of my systems running for some weeks with some debug messages they
certainly are.
But right after boot there is a high chance of success, though, and
it's the easiest check for KVM.

> "grep -E -o 'vmx|svm' /proc/cpuinfo"

This is x86 specific and does not work at all on ARM/arm64.
There is not much to learn about KVM in cpuinfo on arm64.

> I guess maybe the reason is that FVP configuration uses a KVM-unsupport CPU, 
> but I do not know the right configuration, and the FVP documents do not 
> mention anything about KVM.

I doubt that, the normal models should all come with EL2 enabled. The
RevC model definitely works.

Cheers,
Andre

> And this is the FVP booting command in the scripts:
> 
> ===
> 
> /FVP_Base_RevC-2xAEMv8A
> 
>  -C pctl.startup=0.0.0.0
> 
>  -C bp.secure_memory=0
> 
>  -C cluster0.NUM_CORES=1
> 
>  -C cluster1.NUM_CORES=1
> 
>  -C cache_state_modelled=0
> 
>  -C bp.pl011_uart0.untimed_fifos=1
> 
>  -C bp.pl011_uart0.unbuffered_output=1
> 
>  -C bp.pl011_uart0.out_file=uart0-1624328932274439497.log
> 
>  -C bp.pl011_uart1.out_file=uart1-1624328932274439497.log
> 
>  -C 
> bp.secureflashloader.fname=/build-poky/tmp-poky/deploy/images/fvp-base/bl1-fvp.bin
> 
>  -C 
> bp.flashloader0.fname=/build-poky/tmp-poky/deploy/images/fvp-base/fip-fvp.bin
> 
>  -C bp.hostbridge.interfaceName=tap0
> 
>  -C bp.smsc_91c111.enabled=1
> 
>  --data 
> cluster0.cpu0=/build-poky/tmp-poky/deploy/images/fvp-base/Image@0x8008
> 
>  --data 
> cluster0.cpu0=/build-poky/tmp-poky/deploy/images/fvp-base/fvp-base-gicv3-psci-custom.dtb@0x8300
> 
>  -C bp.ve_sysregs.mmbSiteDefault=0
> 
>  -C bp.ve_sysregs.exit_on_shutdown=1
> 
>  -C 
> bp.virtioblockdevice.image_path=/build-poky/tmp-poky/deploy/images/fvp-base/core-image-minimal-fvp-base.disk.img
> 
> ===
> 
> 
> 
> If you can provide any kind of help, I appreciate it very much.
> 
> 
> From: Andre Przywara 
> Sent: Wednesday, April 14, 2021 16:50
> To: 胤桦 陈 
> Cc: kvmarm@lists.cs.columbia.edu 
> Subject: Re: KVM/ARM64: Booting KVM on FVP/fastmodels
> 
> On Wed, 14 Apr 2021 02:37:07 +
> 胤桦 陈  wrote:
> 
> > Hi, Andre
> >
> > Do you mean that if I boot Linux on FVP, then I can run KVM on FVP? Since 
> > KVM is just a module in Linux?  
> 
> Well, on ARM it's not a kernel module, but built-in to the kernel
> image, but yes: You can run any normal KVM enabled kernel on
> it. So just use the same recipe you would use on any o

Re: KVM/ARM64: Booting KVM on FVP/fastmodels

2021-04-14 Thread Andre Przywara
On Wed, 14 Apr 2021 02:37:07 +
胤桦 陈  wrote:

> Hi, Andre
> 
> Do you mean that if I boot Linux on FVP, then I can run KVM on FVP? Since KVM 
> is just a module in Linux?

Well, on ARM it's not a kernel module, but built-in to the kernel
image, but yes: You can run any normal KVM enabled kernel on
it. So just use the same recipe you would use on any other system to
run KVM guests.

Cheers,
Andre
 
> 
> From: André Przywara 
> Sent: Tuesday, March 30, 2021 18:22
> To: yinhua_c...@outlook.com ; 
> kvmarm@lists.cs.columbia.edu 
> Subject: Re: KVM/ARM64: Booting KVM on FVP/fastmodels
> 
> On 29/03/2021 13:13, yinhua_c...@outlook.com wrote:
> 
> Hi,
> 
> > I want to boot KVM on simulators.
> >
> > I don't want to use QEMU since some features are only supported on
> > FVP/fastmodels now.
> >
> > However, I cannot find documents/blogs/wiki about booting KVM on
> > FVP/fastmodels.
> >
> > Does KVM support running on FVP?  
> 
> The FVP emulates the full architecture, including all exception levels
> (so also EL2), and the virtualization support of the GIC and the Generic
> Timer.
> So yes, the models fully support KVM (or any other hypervisor, for that
> matter), and are in fact often used for developing KVM support of new
> hardware features.
> 
> So what are the problems that you are facing? Just running a kernel like
> you would normally do on the model should work out of the box.
> If you describe your setup and the error messages, we can probably help
> you better.
> 
> Cheers,
> Andre
> 
> >
> > Appreciate for your help!
> >
> > Sincerely,
> > Yinhua
> >
> > ___
> > kvmarm mailing list
> > kvmarm@lists.cs.columbia.edu
> > https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
> >  
> 

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [kvm-unit-tests PATCH v2 2/6] arm/arm64: Remove dcache_line_size global variable

2021-03-23 Thread Andre Przywara
On Mon, 22 Mar 2021 15:06:37 +
Alexandru Elisei  wrote:

> Compute the dcache line size when doing dcache maintenance instead of using
> a global variable computed in setup(), which allows us to do dcache
> maintenance at any point in the boot process. This will be useful for
> running as an EFI app and it also aligns our implementation to that of the
> Linux kernel. As a result, the dcache_by_line_op assembly has been modified
> to take a range described by start address and size, instead of start and
> end addresses.
> 
> For consistency, the arm code has been similary modified.
> 
> Signed-off-by: Alexandru Elisei 

Thanks for the changes, looks good now.

Reviewed-by: Andre Przywara 

Cheers,
Andre

> ---
>  lib/arm/asm/assembler.h   | 53 ++
>  lib/arm/asm/processor.h   |  7 -
>  lib/arm64/asm/assembler.h | 54 +++
>  lib/arm64/asm/processor.h |  7 -
>  lib/arm/setup.c   |  7 -
>  arm/cstart.S  | 18 +++--
>  arm/cstart64.S| 16 ++--
>  7 files changed, 112 insertions(+), 50 deletions(-)
>  create mode 100644 lib/arm/asm/assembler.h
>  create mode 100644 lib/arm64/asm/assembler.h
> 
> diff --git a/lib/arm/asm/assembler.h b/lib/arm/asm/assembler.h
> new file mode 100644
> index ..dfd3c51bf6ad
> --- /dev/null
> +++ b/lib/arm/asm/assembler.h
> @@ -0,0 +1,53 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Based on several files from Linux version v5.10: 
> arch/arm/mm/proc-macros.S,
> + * arch/arm/mm/proc-v7.S.
> + */
> +
> +#ifndef __ASSEMBLY__
> +#error "Only include this from assembly code"
> +#endif
> +
> +#ifndef __ASM_ASSEMBLER_H
> +#define __ASM_ASSEMBLER_H
> +
> +/*
> + * dcache_line_size - get the minimum D-cache line size from the CTR register
> + * on ARMv7.
> + */
> + .macro  dcache_line_size, reg, tmp
> + mrc p15, 0, \tmp, c0, c0, 1 // read ctr
> + lsr \tmp, \tmp, #16
> + and \tmp, \tmp, #0xf// cache line size encoding
> + mov \reg, #4// bytes per word
> + mov \reg, \reg, lsl \tmp// actual cache line size
> + .endm
> +
> +/*
> + * Macro to perform a data cache maintenance for the interval
> + * [addr, addr + size).
> + *
> + *   op: operation to execute
> + *   domain  domain used in the dsb instruction
> + *   addr:   starting virtual address of the region
> + *   size:   size of the region
> + *   Corrupts:   addr, size, tmp1, tmp2
> + */
> + .macro dcache_by_line_op op, domain, addr, size, tmp1, tmp2
> + dcache_line_size \tmp1, \tmp2
> + add \size, \addr, \size
> + sub \tmp2, \tmp1, #1
> + bic \addr, \addr, \tmp2
> +9998:
> + .ifc\op, dccimvac
> + mcr p15, 0, \addr, c7, c14, 1
> + .else
> + .err
> + .endif
> + add \addr, \addr, \tmp1
> + cmp \addr, \size
> + blo 9998b
> + dsb \domain
> + .endm
> +
> +#endif   /* __ASM_ASSEMBLER_H */
> diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
> index 273366d1fe1c..3c36eac903f0 100644
> --- a/lib/arm/asm/processor.h
> +++ b/lib/arm/asm/processor.h
> @@ -9,11 +9,6 @@
>  #include 
>  #include 
>  
> -#define CTR_DMINLINE_SHIFT   16
> -#define CTR_DMINLINE_MASK(0xf << 16)
> -#define CTR_DMINLINE(x)  \
> - (((x) & CTR_DMINLINE_MASK) >> CTR_DMINLINE_SHIFT)
> -
>  enum vector {
>   EXCPTN_RST,
>   EXCPTN_UND,
> @@ -89,6 +84,4 @@ static inline u32 get_ctr(void)
>   return read_sysreg(CTR);
>  }
>  
> -extern unsigned long dcache_line_size;
> -
>  #endif /* _ASMARM_PROCESSOR_H_ */
> diff --git a/lib/arm64/asm/assembler.h b/lib/arm64/asm/assembler.h
> new file mode 100644
> index ..0a6ab9720bdd
> --- /dev/null
> +++ b/lib/arm64/asm/assembler.h
> @@ -0,0 +1,54 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Based on the file arch/arm64/include/asm/assembled.h from Linux v5.10, 
> which
> + * in turn is based on arch/arm/include/asm/assembler.h and
> + * arch/arm/mm/proc-macros.S
> + *
> + * Copyright (C) 1996-2000 Russell King
> + * Copyright (C) 2012 ARM Ltd.
> + */
> +
> +#ifndef __ASSEMBLY__
> +#error "Only include this from assembly code"
> +#endif
> +
> +#ifndef __ASM_ASSEMBLER_H
> +#define __ASM_ASSEMBLER_H
> +
> +/*
> + * raw_dcache_line_size - get the minimum D-cache line size on this CPU
> + * from the CTR register.
> + */
> + .macro  raw_dcache_line_siz

Re: [kvm-unit-tests PATCH 2/6] arm/arm64: Remove dcache_line_size global variable

2021-03-16 Thread Andre Przywara
On Mon, 15 Mar 2021 15:46:09 +
Alexandru Elisei  wrote:

Hi Alex,

> On 3/4/21 3:00 PM, Andre Przywara wrote:
> > On Sat, 27 Feb 2021 10:41:57 +
> > Alexandru Elisei  wrote:
> >  
> >> Compute the dcache line size when doing dcache maintenance instead of using
> >> a global variable computed in setup(), which allows us to do dcache
> >> maintenance at any point in the boot process. This will be useful for
> >> running as an EFI app and it also aligns our implementation to that of the
> >> Linux kernel.  
> > Can you add that this changes the semantic of dcache_by_line_op to use
> > the size instead of the end address?  
> 
> Sure, I can do that. The dcache_by_line_op was never visible to code outside
> assembly, and it was only used by asm_mmu_disable, so no other callers are
> affected by this change.

Thanks, just a short sentence suffices. I was just mentioning this
since many cache-op wrappers I have seen use (start,stop) pairs, while
I actually think (start,length) is more practical. So it just deserves
a short mentioning in case anyone was familiar with the previous
arguments and wonders what's going on.

> >  
> >> For consistency, the arm code has been similary modified.
> >>
> >> Signed-off-by: Alexandru Elisei 
> >> ---
> >>  lib/arm/asm/assembler.h   | 44 
> >>  lib/arm/asm/processor.h   |  7 --
> >>  lib/arm64/asm/assembler.h | 53 +++
> >>  lib/arm64/asm/processor.h |  7 --
> >>  lib/arm/setup.c   |  7 --
> >>  arm/cstart.S  | 18 +++--
> >>  arm/cstart64.S| 16 ++--
> >>  7 files changed, 102 insertions(+), 50 deletions(-)
> >>  create mode 100644 lib/arm/asm/assembler.h
> >>  create mode 100644 lib/arm64/asm/assembler.h
> >>
> >> diff --git a/lib/arm/asm/assembler.h b/lib/arm/asm/assembler.h
> >> new file mode 100644
> >> index ..6b932df86204
> >> --- /dev/null
> >> +++ b/lib/arm/asm/assembler.h
> >> @@ -0,0 +1,44 @@
> >> +/* SPDX-License-Identifier: GPL-2.0 */
> >> +/*
> >> + * Based on several files from Linux version v5.10: 
> >> arch/arm/mm/proc-macros.S,
> >> + * arch/arm/mm/proc-v7.S.
> >> + */
> >> +
> >> +/*
> >> + * dcache_line_size - get the minimum D-cache line size from the CTR 
> >> register
> > `> + * on ARMv7.  
> 
> Well, it's in the arm directory and there's a file with the same name under
> lib/arm64/asm/, so I don't think there's any room for confusion here.

Mmh, this v7 line was already in there, and I didn't complain, it was
apparently just a stray character sneaking in the reply which made this
look like a comment?

> 
> >> + */
> >> +  .macro  dcache_line_size, reg, tmp
> >> +  mrc p15, 0, \tmp, c0, c0, 1 // read ctr
> >> +  lsr \tmp, \tmp, #16
> >> +  and \tmp, \tmp, #0xf// cache line size encoding
> >> +  mov \reg, #4// bytes per word
> >> +  mov \reg, \reg, lsl \tmp// actual cache line size
> >> +  .endm
> >> +
> >> +/*
> >> + * Macro to perform a data cache maintenance for the interval
> >> + * [addr, addr + size).
> >> + *
> >> + *op: operation to execute
> >> + *domain  domain used in the dsb instruction
> >> + *addr:   starting virtual address of the region
> >> + *size:   size of the region
> >> + *Corrupts:   addr, size, tmp1, tmp2
> >> + */
> >> +  .macro dcache_by_line_op op, domain, addr, size, tmp1, tmp2
> >> +  dcache_line_size \tmp1, \tmp2
> >> +  add \size, \addr, \size
> >> +  sub \tmp2, \tmp1, #1
> >> +  bic \addr, \addr, \tmp2  
> > Just a nit, but since my brain was in assembly land: We could skip tmp2,
> > by adding back #1 to tmp1 after the bic.
> > Same for the arm64 code.  
> 
> Using one less temporary register wouldn't help with register pressure:
> 
> - On arm, registers r0-r3 are used, which ARM IHI 0042F says that they can be 
> used
> as scratch registers and the caller will save their contents before the 
> calling
> the function (or not use them at all).
> 
> - On arm64, register x0-x3 are used, which have a similar usage according to 
> ARM
> IHI 0055B.
> 
> Using one less temporary register means one more instruction, but not relevant
> since the macro will 

[PATCH kvmtool v3 22/22] hw/rtc: ARM/arm64: Use MMIO at higher addresses

2021-03-15 Thread Andre Przywara
Using the RTC device at its legacy I/O address as set by IBM in 1981
was a kludge we used for simplicity on ARM platforms as well.
However this imposes problems due to their missing alignment and overlap
with the PCI I/O address space.

Now that we can switch a device easily between using ioports and
MMIO, let's move the RTC out of the first 4K of memory on ARM platforms.

That should be transparent for well behaved guests, since the change is
naturally reflected in the device tree.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 arm/include/arm-common/kvm-arch.h |  7 +--
 hw/rtc.c  | 24 
 2 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/arm/include/arm-common/kvm-arch.h 
b/arm/include/arm-common/kvm-arch.h
index bf34d742..436b67b8 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -14,8 +14,8 @@
  * +---++---+---++-+-+---..
  * |  PCI  || plat  |   || | |
  * |  I/O  || MMIO: | Flash | virtio | GIC |   PCI   |  DRAM
- * | space || UART  |   |  MMIO  | |  (AXI)  |
- * |   ||   |   || | |
+ * | space || UART, |   |  MMIO  | |  (AXI)  |
+ * |   || RTC   |   || | |
  * +---++---+---++-+-+---..
  */
 
@@ -31,6 +31,9 @@
 #define ARM_UART_MMIO_BASE ARM_MMIO_AREA
 #define ARM_UART_MMIO_SIZE 0x1
 
+#define ARM_RTC_MMIO_BASE  (ARM_UART_MMIO_BASE + ARM_UART_MMIO_SIZE)
+#define ARM_RTC_MMIO_SIZE  0x1
+
 #define KVM_FLASH_MMIO_BASE(ARM_MMIO_AREA + 0x100)
 #define KVM_FLASH_MAX_SIZE 0x100
 
diff --git a/hw/rtc.c b/hw/rtc.c
index ee4c9102..aec31c52 100644
--- a/hw/rtc.c
+++ b/hw/rtc.c
@@ -5,6 +5,15 @@
 
 #include 
 
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#define RTC_BUS_TYPE   DEVICE_BUS_MMIO
+#define RTC_BASE_ADDRESS   ARM_RTC_MMIO_BASE
+#else
+/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
+#define RTC_BUS_TYPE   DEVICE_BUS_IOPORT
+#define RTC_BASE_ADDRESS   0x70
+#endif
+
 /*
  * MC146818 RTC registers
  */
@@ -49,7 +58,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 
*data,
time_t ti;
 
if (is_write) {
-   if (addr == 0x70) { /* index register */
+   if (addr == RTC_BASE_ADDRESS) { /* index register */
u8 value = ioport__read8(data);
 
vcpu->kvm->nmi_disabled = value & (1UL << 7);
@@ -70,7 +79,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 
*data,
return;
}
 
-   if (addr == 0x70)
+   if (addr == RTC_BASE_ADDRESS)   /* index register is write-only */
return;
 
time();
@@ -127,7 +136,7 @@ static void generate_rtc_fdt_node(void *fdt,
u8 irq,
enum irq_type))
 {
-   u64 reg_prop[2] = { cpu_to_fdt64(0x70), cpu_to_fdt64(2) };
+   u64 reg_prop[2] = { cpu_to_fdt64(RTC_BASE_ADDRESS), cpu_to_fdt64(2) };
 
_FDT(fdt_begin_node(fdt, "rtc"));
_FDT(fdt_property_string(fdt, "compatible", "motorola,mc146818"));
@@ -139,7 +148,7 @@ static void generate_rtc_fdt_node(void *fdt,
 #endif
 
 struct device_header rtc_dev_hdr = {
-   .bus_type = DEVICE_BUS_IOPORT,
+   .bus_type = RTC_BUS_TYPE,
.data = generate_rtc_fdt_node,
 };
 
@@ -151,8 +160,8 @@ int rtc__init(struct kvm *kvm)
if (r < 0)
return r;
 
-   /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-   r = kvm__register_pio(kvm, 0x0070, 2, cmos_ram_io, NULL);
+   r = kvm__register_iotrap(kvm, RTC_BASE_ADDRESS, 2, cmos_ram_io, NULL,
+RTC_BUS_TYPE);
if (r < 0)
goto out_device;
 
@@ -170,8 +179,7 @@ dev_init(rtc__init);
 
 int rtc__exit(struct kvm *kvm)
 {
-   /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-   kvm__deregister_pio(kvm, 0x0070);
+   kvm__deregister_iotrap(kvm, RTC_BASE_ADDRESS, RTC_BUS_TYPE);
 
return 0;
 }
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 21/22] hw/serial: ARM/arm64: Use MMIO at higher addresses

2021-03-15 Thread Andre Przywara
Using the UART devices at their legacy I/O addresses as set by IBM in
1981 was a kludge we used for simplicity on ARM platforms as well.
However this imposes problems due to their missing alignment and overlap
with the PCI I/O address space.

Now that we can switch a device easily between using ioports and MMIO,
let's move the UARTs out of the first 4K of memory on ARM platforms.

That should be transparent for well behaved guests, since the change is
naturally reflected in the device tree. Even "earlycon" keeps working,
as the stdout-path property is adjusted automatically.

People providing direct earlycon parameters via the command line need to
adjust it to: "earlycon=uart,mmio,0x100".

Signed-off-by: Andre Przywara 
---
 arm/include/arm-common/kvm-arch.h |  7 ++--
 hw/serial.c   | 54 +--
 2 files changed, 42 insertions(+), 19 deletions(-)

diff --git a/arm/include/arm-common/kvm-arch.h 
b/arm/include/arm-common/kvm-arch.h
index a2e32953..bf34d742 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -13,8 +13,8 @@
  * 0  64K  16M 32M 48M1GB   2GB
  * +---++---+---++-+-+---..
  * |  PCI  || plat  |   || | |
- * |  I/O  || MMIO  | Flash | virtio | GIC |   PCI   |  DRAM
- * | space ||   |   |  MMIO  | |  (AXI)  |
+ * |  I/O  || MMIO: | Flash | virtio | GIC |   PCI   |  DRAM
+ * | space || UART  |   |  MMIO  | |  (AXI)  |
  * |   ||   |   || | |
  * +---++---+---++-+-+---..
  */
@@ -28,6 +28,9 @@
 #define ARM_IOPORT_SIZE(1U << 16)
 
 
+#define ARM_UART_MMIO_BASE ARM_MMIO_AREA
+#define ARM_UART_MMIO_SIZE 0x1
+
 #define KVM_FLASH_MMIO_BASE(ARM_MMIO_AREA + 0x100)
 #define KVM_FLASH_MAX_SIZE 0x100
 
diff --git a/hw/serial.c b/hw/serial.c
index 16af493b..3d533623 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -13,6 +13,24 @@
 
 #include 
 
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#define serial_iobase(nr)  (ARM_UART_MMIO_BASE + (nr) * 0x1000)
+#define serial_irq(nr) (32 + (nr))
+#define SERIAL8250_BUS_TYPEDEVICE_BUS_MMIO
+#else
+#define serial_iobase_0(KVM_IOPORT_AREA + 0x3f8)
+#define serial_iobase_1(KVM_IOPORT_AREA + 0x2f8)
+#define serial_iobase_2(KVM_IOPORT_AREA + 0x3e8)
+#define serial_iobase_3(KVM_IOPORT_AREA + 0x2e8)
+#define serial_irq_0   4
+#define serial_irq_1   3
+#define serial_irq_2   4
+#define serial_irq_3   3
+#define serial_iobase(nr)  serial_iobase_##nr
+#define serial_irq(nr) serial_irq_##nr
+#define SERIAL8250_BUS_TYPEDEVICE_BUS_IOPORT
+#endif
+
 /*
  * This fakes a U6_16550A. The fifo len needs to be 64 as the kernel
  * expects that for autodetection.
@@ -27,7 +45,7 @@ struct serial8250_device {
struct mutexmutex;
u8  id;
 
-   u16 iobase;
+   u32 iobase;
u8  irq;
u8  irq_state;
int txcnt;
@@ -65,56 +83,56 @@ static struct serial8250_device devices[] = {
/* ttyS0 */
[0] = {
.dev_hdr = {
-   .bus_type   = DEVICE_BUS_IOPORT,
+   .bus_type   = SERIAL8250_BUS_TYPE,
.data   = serial8250_generate_fdt_node,
},
.mutex  = MUTEX_INITIALIZER,
 
.id = 0,
-   .iobase = 0x3f8,
-   .irq= 4,
+   .iobase = serial_iobase(0),
+   .irq= serial_irq(0),
 
SERIAL_REGS_SETTING
},
/* ttyS1 */
[1] = {
.dev_hdr = {
-   .bus_type   = DEVICE_BUS_IOPORT,
+   .bus_type   = SERIAL8250_BUS_TYPE,
.data   = serial8250_generate_fdt_node,
},
.mutex  = MUTEX_INITIALIZER,
 
.id = 1,
-   .iobase = 0x2f8,
-   .irq= 3,
+   .iobase = serial_iobase(1),
+   .irq= serial_irq(1),
 
SERIAL_REGS_SETTING
},
/* ttyS2 */
[2] = {
.dev_hdr = {
-   .bus_type   = DEVICE_BUS_IOPORT,
+   .bus_type   = SERIAL8250_BUS_TYPE,
.data   = serial8250_generate_fdt_node,
   

[PATCH kvmtool v3 20/22] arm: Reorganise and document memory map

2021-03-15 Thread Andre Przywara
The hardcoded memory map we expose to a guest is currently described
using a series of partially interconnected preprocessor constants,
which is hard to read and follow.

In preparation for moving the UART and RTC to some different MMIO
region, document the current map with some ASCII art, and clean up the
definition of the sections.

This changes the only internally used value of ARM_MMIO_AREA, to better
align with its actual meaning and future extensions.

No functional change.

Signed-off-by: Andre Przywara 
---
 arm/include/arm-common/kvm-arch.h | 41 ++-
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/arm/include/arm-common/kvm-arch.h 
b/arm/include/arm-common/kvm-arch.h
index d84e50cd..a2e32953 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -7,14 +7,33 @@
 
 #include "arm-common/gic.h"
 
+/*
+ * The memory map used for ARM guests (not to scale):
+ *
+ * 0  64K  16M 32M 48M1GB   2GB
+ * +---++---+---++-+-+---..
+ * |  PCI  || plat  |   || | |
+ * |  I/O  || MMIO  | Flash | virtio | GIC |   PCI   |  DRAM
+ * | space ||   |   |  MMIO  | |  (AXI)  |
+ * |   ||   |   || | |
+ * +---++---+---++-+-+---..
+ */
+
 #define ARM_IOPORT_AREA_AC(0x, UL)
-#define ARM_FLASH_AREA _AC(0x0200, UL)
-#define ARM_MMIO_AREA  _AC(0x0300, UL)
+#define ARM_MMIO_AREA  _AC(0x0100, UL)
 #define ARM_AXI_AREA   _AC(0x4000, UL)
 #define ARM_MEMORY_AREA_AC(0x8000, UL)
 
-#define ARM_LOMAP_MAX_MEMORY   ((1ULL << 32) - ARM_MEMORY_AREA)
-#define ARM_HIMAP_MAX_MEMORY   ((1ULL << 40) - ARM_MEMORY_AREA)
+#define KVM_IOPORT_AREAARM_IOPORT_AREA
+#define ARM_IOPORT_SIZE(1U << 16)
+
+
+#define KVM_FLASH_MMIO_BASE(ARM_MMIO_AREA + 0x100)
+#define KVM_FLASH_MAX_SIZE 0x100
+
+#define KVM_VIRTIO_MMIO_AREA   (KVM_FLASH_MMIO_BASE + KVM_FLASH_MAX_SIZE)
+#define ARM_VIRTIO_MMIO_SIZE   (ARM_AXI_AREA - \
+   (KVM_VIRTIO_MMIO_AREA + ARM_GIC_SIZE))
 
 #define ARM_GIC_DIST_BASE  (ARM_AXI_AREA - ARM_GIC_DIST_SIZE)
 #define ARM_GIC_CPUI_BASE  (ARM_GIC_DIST_BASE - ARM_GIC_CPUI_SIZE)
@@ -22,19 +41,17 @@
 #define ARM_GIC_DIST_SIZE  0x1
 #define ARM_GIC_CPUI_SIZE  0x2
 
-#define KVM_FLASH_MMIO_BASEARM_FLASH_AREA
-#define KVM_FLASH_MAX_SIZE (ARM_MMIO_AREA - ARM_FLASH_AREA)
 
-#define ARM_IOPORT_SIZE(1U << 16)
-#define ARM_VIRTIO_MMIO_SIZE   (ARM_AXI_AREA - (ARM_MMIO_AREA + ARM_GIC_SIZE))
+#define KVM_PCI_CFG_AREA   ARM_AXI_AREA
 #define ARM_PCI_CFG_SIZE   (1ULL << 24)
+#define KVM_PCI_MMIO_AREA  (KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
 #define ARM_PCI_MMIO_SIZE  (ARM_MEMORY_AREA - \
(ARM_AXI_AREA + ARM_PCI_CFG_SIZE))
 
-#define KVM_IOPORT_AREAARM_IOPORT_AREA
-#define KVM_PCI_CFG_AREA   ARM_AXI_AREA
-#define KVM_PCI_MMIO_AREA  (KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
-#define KVM_VIRTIO_MMIO_AREA   ARM_MMIO_AREA
+
+#define ARM_LOMAP_MAX_MEMORY   ((1ULL << 32) - ARM_MEMORY_AREA)
+#define ARM_HIMAP_MAX_MEMORY   ((1ULL << 40) - ARM_MEMORY_AREA)
+
 
 #define KVM_IOEVENTFD_HAS_PIO  0
 
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 19/22] Remove ioport specific routines

2021-03-15 Thread Andre Przywara
Now that all users of the dedicated ioport trap handler interface are
gone, we can retire the code associated with it.

This removes ioport.c and ioport.h, along with removing prototypes from
other header files.

This also transfers the responsibility for port I/O trap handling
entirely into the new routine in mmio.c.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 Makefile |   1 -
 include/kvm/ioport.h |  27 --
 include/kvm/kvm.h|   2 -
 ioport.c | 195 ---
 mmio.c   |   2 +-
 5 files changed, 1 insertion(+), 226 deletions(-)
 delete mode 100644 ioport.c

diff --git a/Makefile b/Makefile
index 35bb1182..94ff5da6 100644
--- a/Makefile
+++ b/Makefile
@@ -56,7 +56,6 @@ OBJS  += framebuffer.o
 OBJS   += guest_compat.o
 OBJS   += hw/rtc.o
 OBJS   += hw/serial.o
-OBJS   += ioport.o
 OBJS   += irq.o
 OBJS   += kvm-cpu.o
 OBJS   += kvm.o
diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
index a61038e2..b6f579cb 100644
--- a/include/kvm/ioport.h
+++ b/include/kvm/ioport.h
@@ -1,13 +1,8 @@
 #ifndef KVM__IOPORT_H
 #define KVM__IOPORT_H
 
-#include "kvm/devices.h"
 #include "kvm/kvm-cpu.h"
-#include "kvm/rbtree-interval.h"
-#include "kvm/fdt.h"
 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -15,30 +10,8 @@
 /* some ports we reserve for own use */
 #define IOPORT_DBG 0xe0
 
-struct kvm;
-
-struct ioport {
-   struct rb_int_node  node;
-   struct ioport_operations*ops;
-   void*priv;
-   struct device_headerdev_hdr;
-   u32 refcount;
-   boolremove;
-};
-
-struct ioport_operations {
-   bool (*io_in)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size);
-   bool (*io_out)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size);
-};
-
 void ioport__map_irq(u8 *irq);
 
-int __must_check ioport__register(struct kvm *kvm, u16 port, struct 
ioport_operations *ops,
- int count, void *param);
-int ioport__unregister(struct kvm *kvm, u16 port);
-int ioport__init(struct kvm *kvm);
-int ioport__exit(struct kvm *kvm);
-
 static inline u8 ioport__read8(u8 *data)
 {
return *data;
diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
index 306b258a..6c28afa3 100644
--- a/include/kvm/kvm.h
+++ b/include/kvm/kvm.h
@@ -126,8 +126,6 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
 void kvm__irq_trigger(struct kvm *kvm, int irq);
 bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int 
direction, int size, u32 count);
 bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, 
u8 is_write);
-bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
- int direction, int size, u32 count);
 int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void 
*userspace_addr);
 int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void 
*userspace_addr,
  enum kvm_mem_type type);
diff --git a/ioport.c b/ioport.c
deleted file mode 100644
index ce29e7e7..
--- a/ioport.c
+++ /dev/null
@@ -1,195 +0,0 @@
-#include "kvm/ioport.h"
-
-#include "kvm/kvm.h"
-#include "kvm/util.h"
-#include "kvm/rbtree-interval.h"
-#include "kvm/mutex.h"
-
-#include  /* for KVM_EXIT_* */
-#include 
-
-#include 
-#include 
-#include 
-#include 
-
-#define ioport_node(n) rb_entry(n, struct ioport, node)
-
-static DEFINE_MUTEX(ioport_lock);
-
-static struct rb_root  ioport_tree = RB_ROOT;
-
-static struct ioport *ioport_search(struct rb_root *root, u64 addr)
-{
-   struct rb_int_node *node;
-
-   node = rb_int_search_single(root, addr);
-   if (node == NULL)
-   return NULL;
-
-   return ioport_node(node);
-}
-
-static int ioport_insert(struct rb_root *root, struct ioport *data)
-{
-   return rb_int_insert(root, >node);
-}
-
-static void ioport_remove(struct rb_root *root, struct ioport *data)
-{
-   rb_int_erase(root, >node);
-}
-
-static struct ioport *ioport_get(struct rb_root *root, u64 addr)
-{
-   struct ioport *ioport;
-
-   mutex_lock(_lock);
-   ioport = ioport_search(root, addr);
-   if (ioport)
-   ioport->refcount++;
-   mutex_unlock(_lock);
-
-   return ioport;
-}
-
-/* Called with ioport_lock held. */
-static void ioport_unregister(struct rb_root *root, struct ioport *data)
-{
-   ioport_remove(root, data);
-   free(data);
-}
-
-static void ioport_put(struct rb_root *root, struct ioport *data)
-{
-   mutex_lock(_lock);
-   data->refcount--;
-   if (data->remove && data->refcount == 0)
-   ioport_unregister(root, data);
-   mutex_unlock(

[PATCH kvmtool v3 15/22] vfio: Refactor ioport trap handler

2021-03-15 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Adjust the I/O port trap handler to use that new function, and provide
shims to implement the old ioport interface, for now.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 vfio/core.c | 51 ---
 1 file changed, 36 insertions(+), 15 deletions(-)

diff --git a/vfio/core.c b/vfio/core.c
index 0b45e78b..ddd3c2c7 100644
--- a/vfio/core.c
+++ b/vfio/core.c
@@ -81,15 +81,12 @@ out_free_buf:
return ret;
 }
 
-static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
-  u16 port, void *data, int len)
+static bool _vfio_ioport_in(struct vfio_region *region, u32 offset,
+   void *data, int len)
 {
-   u32 val;
-   ssize_t nr;
-   struct vfio_region *region = ioport->priv;
struct vfio_device *vdev = region->vdev;
-
-   u32 offset = port - region->port_base;
+   ssize_t nr;
+   u32 val;
 
if (!(region->info.flags & VFIO_REGION_INFO_FLAG_READ))
return false;
@@ -97,7 +94,7 @@ static bool vfio_ioport_in(struct ioport *ioport, struct 
kvm_cpu *vcpu,
nr = pread(vdev->fd, , len, region->info.offset + offset);
if (nr != len) {
vfio_dev_err(vdev, "could not read %d bytes from I/O port 
0x%x\n",
-len, port);
+len, offset + region->port_base);
return false;
}
 
@@ -118,15 +115,13 @@ static bool vfio_ioport_in(struct ioport *ioport, struct 
kvm_cpu *vcpu,
return true;
 }
 
-static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
-   u16 port, void *data, int len)
+static bool _vfio_ioport_out(struct vfio_region *region, u32 offset,
+void *data, int len)
 {
-   u32 val;
-   ssize_t nr;
-   struct vfio_region *region = ioport->priv;
struct vfio_device *vdev = region->vdev;
+   ssize_t nr;
+   u32 val;
 
-   u32 offset = port - region->port_base;
 
if (!(region->info.flags & VFIO_REGION_INFO_FLAG_WRITE))
return false;
@@ -148,11 +143,37 @@ static bool vfio_ioport_out(struct ioport *ioport, struct 
kvm_cpu *vcpu,
nr = pwrite(vdev->fd, , len, region->info.offset + offset);
if (nr != len)
vfio_dev_err(vdev, "could not write %d bytes to I/O port 0x%x",
-len, port);
+len, offset + region->port_base);
 
return nr == len;
 }
 
+static void vfio_ioport_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+u8 is_write, void *ptr)
+{
+   struct vfio_region *region = ptr;
+   u32 offset = addr - region->port_base;
+
+   if (is_write)
+   _vfio_ioport_out(region, offset, data, len);
+   else
+   _vfio_ioport_in(region, offset, data, len);
+}
+
+static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
+   u16 port, void *data, int len)
+{
+   vfio_ioport_mmio(vcpu, port, data, len, true, ioport->priv);
+   return true;
+}
+
+static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
+  u16 port, void *data, int len)
+{
+   vfio_ioport_mmio(vcpu, port, data, len, false, ioport->priv);
+   return true;
+}
+
 static struct ioport_operations vfio_ioport_ops = {
.io_in  = vfio_ioport_in,
.io_out = vfio_ioport_out,
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 18/22] pci: Switch trap handling to use MMIO handler

2021-03-15 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Merge the existing _in and _out handlers to adhere to that MMIO
interface, and register these using the new registration function.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 pci.c | 82 +--
 1 file changed, 24 insertions(+), 58 deletions(-)

diff --git a/pci.c b/pci.c
index 2e2c0270..d6da79e0 100644
--- a/pci.c
+++ b/pci.c
@@ -87,29 +87,16 @@ static void *pci_config_address_ptr(u16 port)
return base + offset;
 }
 
-static bool pci_config_address_out(struct ioport *ioport, struct kvm_cpu 
*vcpu, u16 port, void *data, int size)
+static void pci_config_address_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+   u32 len, u8 is_write, void *ptr)
 {
-   void *p = pci_config_address_ptr(port);
+   void *p = pci_config_address_ptr(addr);
 
-   memcpy(p, data, size);
-
-   return true;
-}
-
-static bool pci_config_address_in(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
-{
-   void *p = pci_config_address_ptr(port);
-
-   memcpy(data, p, size);
-
-   return true;
+   if (is_write)
+   memcpy(p, data, len);
+   else
+   memcpy(data, p, len);
 }
-
-static struct ioport_operations pci_config_address_ops = {
-   .io_in  = pci_config_address_in,
-   .io_out = pci_config_address_out,
-};
-
 static bool pci_device_exists(u8 bus_number, u8 device_number, u8 
function_number)
 {
union pci_config_address pci_config_address;
@@ -125,49 +112,27 @@ static bool pci_device_exists(u8 bus_number, u8 
device_number, u8 function_numbe
return !IS_ERR_OR_NULL(device__find_dev(DEVICE_BUS_PCI, device_number));
 }
 
-static bool pci_config_data_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
-{
-   union pci_config_address pci_config_address;
-
-   if (size > 4)
-   size = 4;
-
-   pci_config_address.w = ioport__read32(_config_address_bits);
-   /*
-* If someone accesses PCI configuration space offsets that are not
-* aligned to 4 bytes, it uses ioports to signify that.
-*/
-   pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
-
-   pci__config_wr(vcpu->kvm, pci_config_address, data, size);
-
-   return true;
-}
-
-static bool pci_config_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
+static void pci_config_data_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+u32 len, u8 is_write, void *kvm)
 {
union pci_config_address pci_config_address;
 
-   if (size > 4)
-   size = 4;
+   if (len > 4)
+   len = 4;
 
pci_config_address.w = ioport__read32(_config_address_bits);
/*
 * If someone accesses PCI configuration space offsets that are not
 * aligned to 4 bytes, it uses ioports to signify that.
 */
-   pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
+   pci_config_address.reg_offset = addr - PCI_CONFIG_DATA;
 
-   pci__config_rd(vcpu->kvm, pci_config_address, data, size);
-
-   return true;
+   if (is_write)
+   pci__config_wr(vcpu->kvm, pci_config_address, data, len);
+   else
+   pci__config_rd(vcpu->kvm, pci_config_address, data, len);
 }
 
-static struct ioport_operations pci_config_data_ops = {
-   .io_in  = pci_config_data_in,
-   .io_out = pci_config_data_out,
-};
-
 static int pci_activate_bar(struct kvm *kvm, struct pci_device_header *pci_hdr,
int bar_num)
 {
@@ -512,11 +477,12 @@ int pci__init(struct kvm *kvm)
 {
int r;
 
-   r = ioport__register(kvm, PCI_CONFIG_DATA + 0, _config_data_ops, 4, 
NULL);
+   r = kvm__register_pio(kvm, PCI_CONFIG_DATA, 4,
+pci_config_data_mmio, NULL);
if (r < 0)
return r;
-
-   r = ioport__register(kvm, PCI_CONFIG_ADDRESS + 0, 
_config_address_ops, 4, NULL);
+   r = kvm__register_pio(kvm, PCI_CONFIG_ADDRESS, 4,
+pci_config_address_mmio, NULL);
if (r < 0)
goto err_unregister_data;
 
@@ -528,17 +494,17 @@ int pci__init(struct kvm *kvm)
return 0;
 
 err_unregister_addr:
-   ioport__unregister(kvm, PCI_CONFIG_ADDRESS);
+   kvm__deregister_pio(kvm, PCI_CONFIG_ADDRESS);
 err_unregister_data:
-   ioport__unregister(kvm, PCI_CONFIG_DATA);
+   kvm__deregister_pio(kvm, PCI_CONFIG_DATA);
return r;
 }
 dev_base_init(pci__init);
 
 int pci__exit(struct kvm *kvm)
 {
-   ioport__unregister(kvm, PCI_CONFIG_DATA);
-   ioport__unregister(kvm, PCI_CONFIG_ADDRESS);
+   kvm__deregist

[PATCH kvmtool v3 17/22] virtio: Switch trap handling to use MMIO handler

2021-03-15 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Adjust the existing MMIO callback routine to automatically determine
the region this trap came through, and call the existing I/O handlers.
Register the ioport region using the new registration function.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 virtio/pci.c | 46 ++
 1 file changed, 14 insertions(+), 32 deletions(-)

diff --git a/virtio/pci.c b/virtio/pci.c
index 6eea6c68..eb91f512 100644
--- a/virtio/pci.c
+++ b/virtio/pci.c
@@ -178,15 +178,6 @@ static bool virtio_pci__data_in(struct kvm_cpu *vcpu, 
struct virtio_device *vdev
return ret;
 }
 
-static bool virtio_pci__io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
-{
-   struct virtio_device *vdev = ioport->priv;
-   struct virtio_pci *vpci = vdev->virtio;
-   unsigned long offset = port - virtio_pci__port_addr(vpci);
-
-   return virtio_pci__data_in(vcpu, vdev, offset, data, size);
-}
-
 static void update_msix_map(struct virtio_pci *vpci,
struct msix_table *msix_entry, u32 vecnum)
 {
@@ -334,20 +325,6 @@ static bool virtio_pci__data_out(struct kvm_cpu *vcpu, 
struct virtio_device *vde
return ret;
 }
 
-static bool virtio_pci__io_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
-{
-   struct virtio_device *vdev = ioport->priv;
-   struct virtio_pci *vpci = vdev->virtio;
-   unsigned long offset = port - virtio_pci__port_addr(vpci);
-
-   return virtio_pci__data_out(vcpu, vdev, offset, data, size);
-}
-
-static struct ioport_operations virtio_pci__io_ops = {
-   .io_in  = virtio_pci__io_in,
-   .io_out = virtio_pci__io_out,
-};
-
 static void virtio_pci__msix_mmio_callback(struct kvm_cpu *vcpu,
   u64 addr, u8 *data, u32 len,
   u8 is_write, void *ptr)
@@ -455,12 +432,19 @@ static void virtio_pci__io_mmio_callback(struct kvm_cpu 
*vcpu,
 {
struct virtio_device *vdev = ptr;
struct virtio_pci *vpci = vdev->virtio;
-   u32 mmio_addr = virtio_pci__mmio_addr(vpci);
+   u32 ioport_addr = virtio_pci__port_addr(vpci);
+   u32 base_addr;
+
+   if (addr >= ioport_addr &&
+   addr < ioport_addr + pci__bar_size(>pci_hdr, 0))
+   base_addr = ioport_addr;
+   else
+   base_addr = virtio_pci__mmio_addr(vpci);
 
if (!is_write)
-   virtio_pci__data_in(vcpu, vdev, addr - mmio_addr, data, len);
+   virtio_pci__data_in(vcpu, vdev, addr - base_addr, data, len);
else
-   virtio_pci__data_out(vcpu, vdev, addr - mmio_addr, data, len);
+   virtio_pci__data_out(vcpu, vdev, addr - base_addr, data, len);
 }
 
 static int virtio_pci__bar_activate(struct kvm *kvm,
@@ -478,10 +462,8 @@ static int virtio_pci__bar_activate(struct kvm *kvm,
 
switch (bar_num) {
case 0:
-   r = ioport__register(kvm, bar_addr, _pci__io_ops,
-bar_size, vdev);
-   if (r > 0)
-   r = 0;
+   r = kvm__register_pio(kvm, bar_addr, bar_size,
+ virtio_pci__io_mmio_callback, vdev);
break;
case 1:
r =  kvm__register_mmio(kvm, bar_addr, bar_size, false,
@@ -510,7 +492,7 @@ static int virtio_pci__bar_deactivate(struct kvm *kvm,
 
switch (bar_num) {
case 0:
-   r = ioport__unregister(kvm, bar_addr);
+   r = kvm__deregister_pio(kvm, bar_addr);
break;
case 1:
case 2:
@@ -625,7 +607,7 @@ int virtio_pci__exit(struct kvm *kvm, struct virtio_device 
*vdev)
virtio_pci__reset(kvm, vdev);
kvm__deregister_mmio(kvm, virtio_pci__mmio_addr(vpci));
kvm__deregister_mmio(kvm, virtio_pci__msix_io_addr(vpci));
-   ioport__unregister(kvm, virtio_pci__port_addr(vpci));
+   kvm__deregister_pio(kvm, virtio_pci__port_addr(vpci));
 
return 0;
 }
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 16/22] vfio: Switch to new ioport trap handlers

2021-03-15 Thread Andre Przywara
Now that the vfio device has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 vfio/core.c | 37 ++---
 1 file changed, 10 insertions(+), 27 deletions(-)

diff --git a/vfio/core.c b/vfio/core.c
index ddd3c2c7..3ff2c0b0 100644
--- a/vfio/core.c
+++ b/vfio/core.c
@@ -81,7 +81,7 @@ out_free_buf:
return ret;
 }
 
-static bool _vfio_ioport_in(struct vfio_region *region, u32 offset,
+static bool vfio_ioport_in(struct vfio_region *region, u32 offset,
void *data, int len)
 {
struct vfio_device *vdev = region->vdev;
@@ -115,7 +115,7 @@ static bool _vfio_ioport_in(struct vfio_region *region, u32 
offset,
return true;
 }
 
-static bool _vfio_ioport_out(struct vfio_region *region, u32 offset,
+static bool vfio_ioport_out(struct vfio_region *region, u32 offset,
 void *data, int len)
 {
struct vfio_device *vdev = region->vdev;
@@ -155,30 +155,11 @@ static void vfio_ioport_mmio(struct kvm_cpu *vcpu, u64 
addr, u8 *data, u32 len,
u32 offset = addr - region->port_base;
 
if (is_write)
-   _vfio_ioport_out(region, offset, data, len);
+   vfio_ioport_out(region, offset, data, len);
else
-   _vfio_ioport_in(region, offset, data, len);
+   vfio_ioport_in(region, offset, data, len);
 }
 
-static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
-   u16 port, void *data, int len)
-{
-   vfio_ioport_mmio(vcpu, port, data, len, true, ioport->priv);
-   return true;
-}
-
-static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
-  u16 port, void *data, int len)
-{
-   vfio_ioport_mmio(vcpu, port, data, len, false, ioport->priv);
-   return true;
-}
-
-static struct ioport_operations vfio_ioport_ops = {
-   .io_in  = vfio_ioport_in,
-   .io_out = vfio_ioport_out,
-};
-
 static void vfio_mmio_access(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 u8 is_write, void *ptr)
 {
@@ -223,9 +204,11 @@ static int vfio_setup_trap_region(struct kvm *kvm, struct 
vfio_device *vdev,
  struct vfio_region *region)
 {
if (region->is_ioport) {
-   int port = ioport__register(kvm, region->port_base,
-  _ioport_ops, region->info.size,
-  region);
+   int port;
+
+   port = kvm__register_pio(kvm, region->port_base,
+region->info.size, vfio_ioport_mmio,
+region);
if (port < 0)
return port;
return 0;
@@ -292,7 +275,7 @@ void vfio_unmap_region(struct kvm *kvm, struct vfio_region 
*region)
munmap(region->host_addr, region->info.size);
region->host_addr = NULL;
} else if (region->is_ioport) {
-   ioport__unregister(kvm, region->port_base);
+   kvm__deregister_pio(kvm, region->port_base);
} else {
kvm__deregister_mmio(kvm, region->guest_phys_addr);
}
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 14/22] hw/serial: Switch to new trap handlers

2021-03-15 Thread Andre Przywara
Now that the serial device has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/serial.c | 31 +++
 1 file changed, 3 insertions(+), 28 deletions(-)

diff --git a/hw/serial.c b/hw/serial.c
index 3f797452..16af493b 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -393,26 +393,6 @@ static void serial8250_mmio(struct kvm_cpu *vcpu, u64 
addr, u8 *data, u32 len,
serial8250_in(dev, vcpu, addr - dev->iobase, data);
 }
 
-static bool serial8250_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
- u16 port, void *data, int size)
-{
-   struct serial8250_device *dev = ioport->priv;
-
-   serial8250_mmio(vcpu, port, data, 1, true, dev);
-
-   return true;
-}
-
-static bool serial8250_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
-u16 port, void *data, int size)
-{
-   struct serial8250_device *dev = ioport->priv;
-
-   serial8250_mmio(vcpu, port, data, 1, false, dev);
-
-   return true;
-}
-
 #ifdef CONFIG_HAS_LIBFDT
 
 char *fdt_stdout_path = NULL;
@@ -450,11 +430,6 @@ void serial8250_generate_fdt_node(void *fdt, struct 
device_header *dev_hdr,
 }
 #endif
 
-static struct ioport_operations serial8250_ops = {
-   .io_in  = serial8250_ioport_in,
-   .io_out = serial8250_ioport_out,
-};
-
 static int serial8250__device_init(struct kvm *kvm,
   struct serial8250_device *dev)
 {
@@ -465,7 +440,7 @@ static int serial8250__device_init(struct kvm *kvm,
return r;
 
ioport__map_irq(>irq);
-   r = ioport__register(kvm, dev->iobase, _ops, 8, dev);
+   r = kvm__register_pio(kvm, dev->iobase, 8, serial8250_mmio, dev);
 
return r;
 }
@@ -488,7 +463,7 @@ cleanup:
for (j = 0; j <= i; j++) {
struct serial8250_device *dev = [j];
 
-   ioport__unregister(kvm, dev->iobase);
+   kvm__deregister_pio(kvm, dev->iobase);
device__unregister(>dev_hdr);
}
 
@@ -504,7 +479,7 @@ int serial8250__exit(struct kvm *kvm)
for (i = 0; i < ARRAY_SIZE(devices); i++) {
struct serial8250_device *dev = [i];
 
-   r = ioport__unregister(kvm, dev->iobase);
+   r = kvm__deregister_pio(kvm, dev->iobase);
if (r < 0)
return r;
device__unregister(>dev_hdr);
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 13/22] hw/serial: Refactor trap handler

2021-03-15 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Adjust the trap handler to use that new function, and provide shims to
implement the old ioport interface, for now.

Signed-off-by: Andre Przywara 
---
 hw/serial.c | 50 +-
 1 file changed, 37 insertions(+), 13 deletions(-)

diff --git a/hw/serial.c b/hw/serial.c
index b0465d99..3f797452 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -242,18 +242,14 @@ void serial8250__inject_sysrq(struct kvm *kvm, char sysrq)
sysrq_pending = sysrq;
 }
 
-static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port,
-  void *data, int size)
+static bool serial8250_out(struct serial8250_device *dev, struct kvm_cpu *vcpu,
+  u16 offset, void *data)
 {
-   struct serial8250_device *dev = ioport->priv;
-   u16 offset;
bool ret = true;
char *addr = data;
 
mutex_lock(>mutex);
 
-   offset = port - dev->iobase;
-
switch (offset) {
case UART_TX:
if (dev->lcr & UART_LCR_DLAB) {
@@ -336,16 +332,13 @@ static void serial8250_rx(struct serial8250_device *dev, 
void *data)
}
 }
 
-static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
+static bool serial8250_in(struct serial8250_device *dev, struct kvm_cpu *vcpu,
+ u16 offset, void *data)
 {
-   struct serial8250_device *dev = ioport->priv;
-   u16 offset;
bool ret = true;
 
mutex_lock(>mutex);
 
-   offset = port - dev->iobase;
-
switch (offset) {
case UART_RX:
if (dev->lcr & UART_LCR_DLAB)
@@ -389,6 +382,37 @@ static bool serial8250_in(struct ioport *ioport, struct 
kvm_cpu *vcpu, u16 port,
return ret;
 }
 
+static void serial8250_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+   u8 is_write, void *ptr)
+{
+   struct serial8250_device *dev = ptr;
+
+   if (is_write)
+   serial8250_out(dev, vcpu, addr - dev->iobase, data);
+   else
+   serial8250_in(dev, vcpu, addr - dev->iobase, data);
+}
+
+static bool serial8250_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
+ u16 port, void *data, int size)
+{
+   struct serial8250_device *dev = ioport->priv;
+
+   serial8250_mmio(vcpu, port, data, 1, true, dev);
+
+   return true;
+}
+
+static bool serial8250_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
+u16 port, void *data, int size)
+{
+   struct serial8250_device *dev = ioport->priv;
+
+   serial8250_mmio(vcpu, port, data, 1, false, dev);
+
+   return true;
+}
+
 #ifdef CONFIG_HAS_LIBFDT
 
 char *fdt_stdout_path = NULL;
@@ -427,8 +451,8 @@ void serial8250_generate_fdt_node(void *fdt, struct 
device_header *dev_hdr,
 #endif
 
 static struct ioport_operations serial8250_ops = {
-   .io_in  = serial8250_in,
-   .io_out = serial8250_out,
+   .io_in  = serial8250_ioport_in,
+   .io_out = serial8250_ioport_out,
 };
 
 static int serial8250__device_init(struct kvm *kvm,
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 12/22] hw/vesa: Switch trap handling to use MMIO handler

2021-03-15 Thread Andre Przywara
To be able to use the VESA device with the new generic I/O trap handler,
we need to use the different MMIO handler callback routine.

Replace the existing dummy in and out handlers with a joint dummy
MMIO handler, and register this using the new registration function.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/vesa.c | 19 +--
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/hw/vesa.c b/hw/vesa.c
index 8659a002..7f82cdb4 100644
--- a/hw/vesa.c
+++ b/hw/vesa.c
@@ -43,21 +43,11 @@ static struct framebuffer vesafb = {
.mem_size   = VESA_MEM_SIZE,
 };
 
-static bool vesa_pci_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
+static void vesa_pci_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+   u8 is_write, void *ptr)
 {
-   return true;
 }
 
-static bool vesa_pci_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
-{
-   return true;
-}
-
-static struct ioport_operations vesa_io_ops = {
-   .io_in  = vesa_pci_io_in,
-   .io_out = vesa_pci_io_out,
-};
-
 static int vesa__bar_activate(struct kvm *kvm, struct pci_device_header 
*pci_hdr,
  int bar_num, void *data)
 {
@@ -82,7 +72,8 @@ struct framebuffer *vesa__init(struct kvm *kvm)
BUILD_BUG_ON(VESA_MEM_SIZE < VESA_BPP/8 * VESA_WIDTH * VESA_HEIGHT);
 
vesa_base_addr = pci_get_io_port_block(PCI_IO_SIZE);
-   r = ioport__register(kvm, vesa_base_addr, _io_ops, PCI_IO_SIZE, 
NULL);
+   r = kvm__register_pio(kvm, vesa_base_addr, PCI_IO_SIZE, vesa_pci_io,
+ NULL);
if (r < 0)
goto out_error;
 
@@ -116,7 +107,7 @@ unmap_dev:
 unregister_device:
device__unregister(_device);
 unregister_ioport:
-   ioport__unregister(kvm, vesa_base_addr);
+   kvm__deregister_pio(kvm, vesa_base_addr);
 out_error:
return ERR_PTR(r);
 }
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 11/22] hw/rtc: Switch to new trap handler

2021-03-15 Thread Andre Przywara
Now that the RTC device has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/rtc.c | 21 ++---
 1 file changed, 2 insertions(+), 19 deletions(-)

diff --git a/hw/rtc.c b/hw/rtc.c
index 664d4cb0..ee4c9102 100644
--- a/hw/rtc.c
+++ b/hw/rtc.c
@@ -120,23 +120,6 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 
*data,
}
 }
 
-static bool cmos_ram_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size)
-{
-   cmos_ram_io(vcpu, port, data, size, false, NULL);
-   return true;
-}
-
-static bool cmos_ram_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
-{
-   cmos_ram_io(vcpu, port, data, size, true, NULL);
-   return true;
-}
-
-static struct ioport_operations cmos_ram_ioport_ops = {
-   .io_out = cmos_ram_out,
-   .io_in  = cmos_ram_in,
-};
-
 #ifdef CONFIG_HAS_LIBFDT
 static void generate_rtc_fdt_node(void *fdt,
  struct device_header *dev_hdr,
@@ -169,7 +152,7 @@ int rtc__init(struct kvm *kvm)
return r;
 
/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-   r = ioport__register(kvm, 0x0070, _ram_ioport_ops, 2, NULL);
+   r = kvm__register_pio(kvm, 0x0070, 2, cmos_ram_io, NULL);
if (r < 0)
goto out_device;
 
@@ -188,7 +171,7 @@ dev_init(rtc__init);
 int rtc__exit(struct kvm *kvm)
 {
/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-   ioport__unregister(kvm, 0x0070);
+   kvm__deregister_pio(kvm, 0x0070);
 
return 0;
 }
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 10/22] hw/rtc: Refactor trap handlers

2021-03-15 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide emulation functions compatible with the MMIO prototype.

Merge the two different trap handlers into one function, checking for
read/write and data/index register inside.
Adjust the trap handlers to use that new function, and provide shims to
implement the old ioport interface, for now.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/rtc.c | 70 
 1 file changed, 35 insertions(+), 35 deletions(-)

diff --git a/hw/rtc.c b/hw/rtc.c
index 5483879f..664d4cb0 100644
--- a/hw/rtc.c
+++ b/hw/rtc.c
@@ -42,11 +42,37 @@ static inline unsigned char bin2bcd(unsigned val)
return ((val / 10) << 4) + val % 10;
 }
 
-static bool cmos_ram_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
+static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+   u32 len, u8 is_write, void *ptr)
 {
struct tm *tm;
time_t ti;
 
+   if (is_write) {
+   if (addr == 0x70) { /* index register */
+   u8 value = ioport__read8(data);
+
+   vcpu->kvm->nmi_disabled = value & (1UL << 7);
+   rtc.cmos_idx= value & ~(1UL << 7);
+
+   return;
+   }
+
+   switch (rtc.cmos_idx) {
+   case RTC_REG_C:
+   case RTC_REG_D:
+   /* Read-only */
+   break;
+   default:
+   rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data);
+   break;
+   }
+   return;
+   }
+
+   if (addr == 0x70)
+   return;
+
time();
 
tm = gmtime();
@@ -92,42 +118,23 @@ static bool cmos_ram_data_in(struct ioport *ioport, struct 
kvm_cpu *vcpu, u16 po
ioport__write8(data, rtc.cmos_data[rtc.cmos_idx]);
break;
}
-
-   return true;
 }
 
-static bool cmos_ram_data_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
+static bool cmos_ram_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size)
 {
-   switch (rtc.cmos_idx) {
-   case RTC_REG_C:
-   case RTC_REG_D:
-   /* Read-only */
-   break;
-   default:
-   rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data);
-   break;
-   }
-
+   cmos_ram_io(vcpu, port, data, size, false, NULL);
return true;
 }
 
-static struct ioport_operations cmos_ram_data_ioport_ops = {
-   .io_out = cmos_ram_data_out,
-   .io_in  = cmos_ram_data_in,
-};
-
-static bool cmos_ram_index_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
+static bool cmos_ram_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
 {
-   u8 value = ioport__read8(data);
-
-   vcpu->kvm->nmi_disabled = value & (1UL << 7);
-   rtc.cmos_idx= value & ~(1UL << 7);
-
+   cmos_ram_io(vcpu, port, data, size, true, NULL);
return true;
 }
 
-static struct ioport_operations cmos_ram_index_ioport_ops = {
-   .io_out = cmos_ram_index_out,
+static struct ioport_operations cmos_ram_ioport_ops = {
+   .io_out = cmos_ram_out,
+   .io_in  = cmos_ram_in,
 };
 
 #ifdef CONFIG_HAS_LIBFDT
@@ -162,21 +169,15 @@ int rtc__init(struct kvm *kvm)
return r;
 
/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-   r = ioport__register(kvm, 0x0070, _ram_index_ioport_ops, 1, NULL);
+   r = ioport__register(kvm, 0x0070, _ram_ioport_ops, 2, NULL);
if (r < 0)
goto out_device;
 
-   r = ioport__register(kvm, 0x0071, _ram_data_ioport_ops, 1, NULL);
-   if (r < 0)
-   goto out_ioport;
-
/* Set the VRT bit in Register D to indicate valid RAM and time */
rtc.cmos_data[RTC_REG_D] = RTC_REG_D_VRT;
 
return r;
 
-out_ioport:
-   ioport__unregister(kvm, 0x0070);
 out_device:
device__unregister(_dev_hdr);
 
@@ -188,7 +189,6 @@ int rtc__exit(struct kvm *kvm)
 {
/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
ioport__unregister(kvm, 0x0070);
-   ioport__unregister(kvm, 0x0071);
 
return 0;
 }
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 09/22] x86/ioport: Switch to new trap handlers

2021-03-15 Thread Andre Przywara
Now that the x86 I/O ports have trap handlers adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Since the debug output was done in ioport.c, we would lose this
functionality when moving over to the MMIO handlers. So bring this back
here explicitly, by introducing debug_io().

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 x86/ioport.c | 101 +++
 1 file changed, 37 insertions(+), 64 deletions(-)

diff --git a/x86/ioport.c b/x86/ioport.c
index b198de7a..06b7defb 100644
--- a/x86/ioport.c
+++ b/x86/ioport.c
@@ -8,15 +8,29 @@ static void dummy_io(struct kvm_cpu *vcpu, u64 addr, u8 
*data, u32 len,
 {
 }
 
-static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
+static void debug_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+u8 is_write, void *ptr)
 {
-   dummy_io(vcpu, port, data, size, true, NULL);
-   return 0;
-}
+   if (!vcpu->kvm->cfg.ioport_debug)
+   return;
 
-static struct ioport_operations debug_ops = {
-   .io_out = debug_io_out,
-};
+   fprintf(stderr, "debug port %s from VCPU%lu: port=0x%lx, size=%u",
+   is_write ? "write" : "read", vcpu->cpu_id,
+   (unsigned long)addr, len);
+   if (is_write) {
+   u32 value;
+
+   switch (len) {
+   case 1: value = ioport__read8(data); break;
+   case 2: value = ioport__read16((u16*)data); break;
+   case 4: value = ioport__read32((u32*)data); break;
+   default: value = 0; break;
+   }
+   fprintf(stderr, ", data: 0x%x\n", value);
+   } else {
+   fprintf(stderr, "\n");
+   }
+}
 
 static void seabios_debug_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
 u32 len, u8 is_write, void *ptr)
@@ -31,37 +45,6 @@ static void seabios_debug_io(struct kvm_cpu *vcpu, u64 addr, 
u8 *data,
putchar(ch);
 }
 
-static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
-{
-   seabios_debug_io(vcpu, port, data, size, true, NULL);
-   return 0;
-}
-
-static struct ioport_operations seabios_debug_ops = {
-   .io_out = seabios_debug_io_out,
-};
-
-static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size)
-{
-   dummy_io(vcpu, port, data, size, false, NULL);
-   return true;
-}
-
-static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
-{
-   dummy_io(vcpu, port, data, size, true, NULL);
-   return true;
-}
-
-static struct ioport_operations dummy_read_write_ioport_ops = {
-   .io_in  = dummy_io_in,
-   .io_out = dummy_io_out,
-};
-
-static struct ioport_operations dummy_write_only_ioport_ops = {
-   .io_out = dummy_io_out,
-};
-
 /*
  * The "fast A20 gate"
  */
@@ -76,17 +59,6 @@ static void ps2_control_io(struct kvm_cpu *vcpu, u64 addr, 
u8 *data, u32 len,
ioport__write8(data, 0x02);
 }
 
-static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
-{
-   ps2_control_io(vcpu, port, data, size, false, NULL);
-   return true;
-}
-
-static struct ioport_operations ps2_control_a_ops = {
-   .io_in  = ps2_control_a_io_in,
-   .io_out = dummy_io_out,
-};
-
 void ioport__map_irq(u8 *irq)
 {
 }
@@ -98,75 +70,76 @@ static int ioport__setup_arch(struct kvm *kvm)
/* Legacy ioport setup */
 
/*  - 001F - DMA1 controller */
-   r = ioport__register(kvm, 0x, _read_write_ioport_ops, 32, 
NULL);
+   r = kvm__register_pio(kvm, 0x, 32, dummy_io, NULL);
if (r < 0)
return r;
 
/* 0x0020 - 0x003F - 8259A PIC 1 */
-   r = ioport__register(kvm, 0x0020, _read_write_ioport_ops, 2, 
NULL);
+   r = kvm__register_pio(kvm, 0x0020, 2, dummy_io, NULL);
if (r < 0)
return r;
 
/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
-   r = ioport__register(kvm, 0x0040, _read_write_ioport_ops, 4, 
NULL);
+   r = kvm__register_pio(kvm, 0x0040, 4, dummy_io, NULL);
if (r < 0)
return r;
 
/* 0092 - PS/2 system control port A */
-   r = ioport__register(kvm, 0x0092, _control_a_ops, 1, NULL);
+   r = kvm__register_pio(kvm, 0x0092, 1, ps2_control_io, NULL);
if (r < 0)
return r;
 
/* 0x00A0 - 0x00AF - 8259A PIC 2 */
-   r = ioport__register(kvm, 0x00A0, _read_write_ioport_ops, 2, 
NULL);
+   r = kvm__register_pio(kvm, 0x00A0, 2, dummy_io, NULL);
if (r < 

[PATCH kvmtool v3 08/22] x86/ioport: Refactor trap handlers

2021-03-15 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide emulation functions compatible with the MMIO
prototype.

Adjust the trap handlers to use that new function, and provide shims to
implement the old ioport interface, for now.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 x86/ioport.c | 30 ++
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/x86/ioport.c b/x86/ioport.c
index a8d2bb1a..b198de7a 100644
--- a/x86/ioport.c
+++ b/x86/ioport.c
@@ -3,8 +3,14 @@
 #include 
 #include 
 
+static void dummy_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+u8 is_write, void *ptr)
+{
+}
+
 static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
 {
+   dummy_io(vcpu, port, data, size, true, NULL);
return 0;
 }
 
@@ -12,15 +18,23 @@ static struct ioport_operations debug_ops = {
.io_out = debug_io_out,
 };
 
-static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
+static void seabios_debug_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+u32 len, u8 is_write, void *ptr)
 {
char ch;
 
+   if (!is_write)
+   return;
+
ch = ioport__read8(data);
 
putchar(ch);
+}
 
-   return true;
+static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
+{
+   seabios_debug_io(vcpu, port, data, size, true, NULL);
+   return 0;
 }
 
 static struct ioport_operations seabios_debug_ops = {
@@ -29,11 +43,13 @@ static struct ioport_operations seabios_debug_ops = {
 
 static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size)
 {
+   dummy_io(vcpu, port, data, size, false, NULL);
return true;
 }
 
 static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
 {
+   dummy_io(vcpu, port, data, size, true, NULL);
return true;
 }
 
@@ -50,13 +66,19 @@ static struct ioport_operations dummy_write_only_ioport_ops 
= {
  * The "fast A20 gate"
  */
 
-static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
+static void ps2_control_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+  u8 is_write, void *ptr)
 {
/*
 * A20 is always enabled.
 */
-   ioport__write8(data, 0x02);
+   if (!is_write)
+   ioport__write8(data, 0x02);
+}
 
+static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
+{
+   ps2_control_io(vcpu, port, data, size, false, NULL);
return true;
 }
 
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 07/22] hw/i8042: Switch to new trap handlers

2021-03-15 Thread Andre Przywara
Now that the PC keyboard has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Make the kbd_init() function static on the way.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/i8042.c  | 30 --
 include/kvm/i8042.h |  1 -
 2 files changed, 4 insertions(+), 27 deletions(-)

diff --git a/hw/i8042.c b/hw/i8042.c
index ab82..20be36c4 100644
--- a/hw/i8042.c
+++ b/hw/i8042.c
@@ -325,40 +325,18 @@ static void kbd_io(struct kvm_cpu *vcpu, u64 addr, u8 
*data, u32 len,
ioport__write8(data, value);
 }
 
-/*
- * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
- */
-static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void 
*data, int size)
-{
-   kbd_io(vcpu, port, data, size, false, NULL);
-
-   return true;
-}
-
-static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size)
-{
-   kbd_io(vcpu, port, data, size, true, NULL);
-
-   return true;
-}
-
-static struct ioport_operations kbd_ops = {
-   .io_in  = kbd_in,
-   .io_out = kbd_out,
-};
-
-int kbd__init(struct kvm *kvm)
+static int kbd__init(struct kvm *kvm)
 {
int r;
 
kbd_reset();
state.kvm = kvm;
-   r = ioport__register(kvm, I8042_DATA_REG, _ops, 2, NULL);
+   r = kvm__register_pio(kvm, I8042_DATA_REG, 2, kbd_io, NULL);
if (r < 0)
return r;
-   r = ioport__register(kvm, I8042_COMMAND_REG, _ops, 2, NULL);
+   r = kvm__register_pio(kvm, I8042_COMMAND_REG, 2, kbd_io, NULL);
if (r < 0) {
-   ioport__unregister(kvm, I8042_DATA_REG);
+   kvm__deregister_pio(kvm, I8042_DATA_REG);
return r;
}
 
diff --git a/include/kvm/i8042.h b/include/kvm/i8042.h
index 3b4ab688..cd4ae6bb 100644
--- a/include/kvm/i8042.h
+++ b/include/kvm/i8042.h
@@ -7,6 +7,5 @@ struct kvm;
 
 void mouse_queue(u8 c);
 void kbd_queue(u8 c);
-int kbd__init(struct kvm *kvm);
 
 #endif
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 06/22] hw/i8042: Refactor trap handler

2021-03-15 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO
prototype.

Adjust the trap handler to use that new function, and provide shims to
implement the old ioport interface, for now.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/i8042.c | 68 +++---
 1 file changed, 34 insertions(+), 34 deletions(-)

diff --git a/hw/i8042.c b/hw/i8042.c
index 7d1f9772..ab82 100644
--- a/hw/i8042.c
+++ b/hw/i8042.c
@@ -292,52 +292,52 @@ static void kbd_reset(void)
};
 }
 
-/*
- * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
- */
-static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void 
*data, int size)
+static void kbd_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+  u8 is_write, void *ptr)
 {
-   switch (port) {
-   case I8042_COMMAND_REG: {
-   u8 value = kbd_read_status();
-   ioport__write8(data, value);
+   u8 value;
+
+   if (is_write)
+   value = ioport__read8(data);
+
+   switch (addr) {
+   case I8042_COMMAND_REG:
+   if (is_write)
+   kbd_write_command(vcpu->kvm, value);
+   else
+   value = kbd_read_status();
break;
-   }
-   case I8042_DATA_REG: {
-   u8 value = kbd_read_data();
-   ioport__write8(data, value);
+   case I8042_DATA_REG:
+   if (is_write)
+   kbd_write_data(value);
+   else
+   value = kbd_read_data();
break;
-   }
-   case I8042_PORT_B_REG: {
-   ioport__write8(data, 0x20);
+   case I8042_PORT_B_REG:
+   if (!is_write)
+   value = 0x20;
break;
-   }
default:
-   return false;
+   return;
}
 
+   if (!is_write)
+   ioport__write8(data, value);
+}
+
+/*
+ * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
+ */
+static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void 
*data, int size)
+{
+   kbd_io(vcpu, port, data, size, false, NULL);
+
return true;
 }
 
 static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size)
 {
-   switch (port) {
-   case I8042_COMMAND_REG: {
-   u8 value = ioport__read8(data);
-   kbd_write_command(vcpu->kvm, value);
-   break;
-   }
-   case I8042_DATA_REG: {
-   u8 value = ioport__read8(data);
-   kbd_write_data(value);
-   break;
-   }
-   case I8042_PORT_B_REG: {
-   break;
-   }
-   default:
-   return false;
-   }
+   kbd_io(vcpu, port, data, size, true, NULL);
 
return true;
 }
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 05/22] hw/i8042: Clean up data types

2021-03-15 Thread Andre Przywara
The i8042 is clearly an 8-bit era device, so there is little room for
32-bit registers.
Clean up the data types used.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/i8042.c | 26 +-
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/hw/i8042.c b/hw/i8042.c
index 37a99a2d..7d1f9772 100644
--- a/hw/i8042.c
+++ b/hw/i8042.c
@@ -64,11 +64,11 @@
 struct kbd_state {
struct kvm  *kvm;
 
-   charkq[QUEUE_SIZE]; /* Keyboard queue */
+   u8  kq[QUEUE_SIZE]; /* Keyboard queue */
int kread, kwrite;  /* Indexes into the queue */
int kcount; /* number of elements in queue 
*/
 
-   charmq[QUEUE_SIZE];
+   u8  mq[QUEUE_SIZE];
int mread, mwrite;
int mcount;
 
@@ -82,7 +82,7 @@ struct kbd_state {
 * Some commands (on port 0x64) have arguments;
 * we store the command here while we wait for the argument
 */
-   u32 write_cmd;
+   u8  write_cmd;
 };
 
 static struct kbd_statestate;
@@ -173,9 +173,9 @@ static void kbd_write_command(struct kvm *kvm, u8 val)
 /*
  * Called when the OS reads from port 0x60 (PS/2 data)
  */
-static u32 kbd_read_data(void)
+static u8 kbd_read_data(void)
 {
-   u32 ret;
+   u8 ret;
int i;
 
if (state.kcount != 0) {
@@ -202,9 +202,9 @@ static u32 kbd_read_data(void)
 /*
  * Called when the OS read from port 0x64, the command port
  */
-static u32 kbd_read_status(void)
+static u8 kbd_read_status(void)
 {
-   return (u32)state.status;
+   return state.status;
 }
 
 /*
@@ -212,7 +212,7 @@ static u32 kbd_read_status(void)
  * Things written here are generally arguments to commands previously
  * written to port 0x64 and stored in state.write_cmd
  */
-static void kbd_write_data(u32 val)
+static void kbd_write_data(u8 val)
 {
switch (state.write_cmd) {
case I8042_CMD_CTL_WCTR:
@@ -266,8 +266,8 @@ static void kbd_write_data(u32 val)
break;
default:
break;
-   }
-   break;
+   }
+   break;
case 0:
/* Just send the ID */
kbd_queue(RESPONSE_ACK);
@@ -304,8 +304,8 @@ static bool kbd_in(struct ioport *ioport, struct kvm_cpu 
*vcpu, u16 port, void *
break;
}
case I8042_DATA_REG: {
-   u32 value = kbd_read_data();
-   ioport__write32(data, value);
+   u8 value = kbd_read_data();
+   ioport__write8(data, value);
break;
}
case I8042_PORT_B_REG: {
@@ -328,7 +328,7 @@ static bool kbd_out(struct ioport *ioport, struct kvm_cpu 
*vcpu, u16 port, void
break;
}
case I8042_DATA_REG: {
-   u32 value = ioport__read32(data);
+   u8 value = ioport__read8(data);
kbd_write_data(value);
break;
}
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 04/22] mmio: Extend handling to include ioport emulation

2021-03-15 Thread Andre Przywara
In their core functionality MMIO and I/O port traps are not really
different, yet we still have two totally separate code paths for
handling them. Devices need to decide on one conduit or need to provide
different handler functions for each of them.

Extend the existing MMIO emulation to also cover ioport handlers.
This just adds another RB tree root for holding the I/O port handlers,
but otherwise uses the same tree population and lookup code.
"ioport" or "mmio" just become a flag in the registration function.
Provide wrappers to not break existing users, and allow an easy
transition for the existing ioport handlers.

This also means that ioport handlers now can use the same emulation
callback prototype as MMIO handlers, which means we have to migrate them
over. To allow a smooth transition, we hook up the new I/O emulate
function to the end of the existing ioport emulation code.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 include/kvm/kvm.h | 49 ---
 ioport.c  |  4 +--
 mmio.c| 65 +++
 3 files changed, 102 insertions(+), 16 deletions(-)

diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
index f1f0afd7..306b258a 100644
--- a/include/kvm/kvm.h
+++ b/include/kvm/kvm.h
@@ -27,10 +27,23 @@
 #define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
 #endif
 
+/*
+ * We are reusing the existing DEVICE_BUS_MMIO and DEVICE_BUS_IOPORT constants
+ * from kvm/devices.h to differentiate between registering an I/O port and an
+ * MMIO region.
+ * To avoid collisions with future additions of more bus types, we reserve
+ * a generous 4 bits for the bus mask here.
+ */
+#define IOTRAP_BUS_MASK0xf
+#define IOTRAP_COALESCE(1U << 4)
+
 #define DEFINE_KVM_EXT(ext)\
.name = #ext,   \
.code = ext
 
+struct kvm_cpu;
+typedef void (*mmio_handler_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+   u32 len, u8 is_write, void *ptr);
 typedef void (*fdt_irq_fn)(void *fdt, u8 irq, enum irq_type irq_type);
 
 enum {
@@ -113,6 +126,8 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
 void kvm__irq_trigger(struct kvm *kvm, int irq);
 bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int 
direction, int size, u32 count);
 bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, 
u8 is_write);
+bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
+ int direction, int size, u32 count);
 int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void 
*userspace_addr);
 int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void 
*userspace_addr,
  enum kvm_mem_type type);
@@ -136,10 +151,36 @@ static inline int kvm__reserve_mem(struct kvm *kvm, u64 
guest_phys, u64 size)
 KVM_MEM_TYPE_RESERVED);
 }
 
-int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 
phys_addr_len, bool coalesce,
-   void (*mmio_fn)(struct kvm_cpu *vcpu, u64 
addr, u8 *data, u32 len, u8 is_write, void *ptr),
-   void *ptr);
-bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
+int __must_check kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 len,
+ mmio_handler_fn mmio_fn, void *ptr,
+ unsigned int flags);
+
+static inline
+int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr,
+   u64 phys_addr_len, bool coalesce,
+   mmio_handler_fn mmio_fn, void *ptr)
+{
+   return kvm__register_iotrap(kvm, phys_addr, phys_addr_len, mmio_fn, ptr,
+   DEVICE_BUS_MMIO | (coalesce ? IOTRAP_COALESCE : 0));
+}
+static inline
+int __must_check kvm__register_pio(struct kvm *kvm, u16 port, u16 len,
+  mmio_handler_fn mmio_fn, void *ptr)
+{
+   return kvm__register_iotrap(kvm, port, len, mmio_fn, ptr,
+   DEVICE_BUS_IOPORT);
+}
+
+bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int 
flags);
+static inline bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
+{
+   return kvm__deregister_iotrap(kvm, phys_addr, DEVICE_BUS_MMIO);
+}
+static inline bool kvm__deregister_pio(struct kvm *kvm, u16 port)
+{
+   return kvm__deregister_iotrap(kvm, port, DEVICE_BUS_IOPORT);
+}
+
 void kvm__reboot(struct kvm *kvm);
 void kvm__pause(struct kvm *kvm);
 void kvm__continue(struct kvm *kvm);
diff --git a/ioport.c b/ioport.c
index e0123f27..ce29e7e7 100644
--- a/ioport.c
+++ b/ioport.c
@@ -162,7 +162,8 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void 
*data, int direction,
 
entry = ioport_get(_tree, port);
if (!entry)
-   goto o

[PATCH kvmtool v3 03/22] ioport: Retire .generate_fdt_node functionality

2021-03-15 Thread Andre Przywara
The ioport routines support a special way of registering FDT node
generator functions. There is no reason to have this separate from the
already existing way via the device header.

Now that the only user of this special ioport variety has been
transferred, we can retire this code, to simplify ioport handling.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 include/kvm/ioport.h |  4 
 ioport.c | 34 --
 2 files changed, 38 deletions(-)

diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
index d0213541..a61038e2 100644
--- a/include/kvm/ioport.h
+++ b/include/kvm/ioport.h
@@ -29,10 +29,6 @@ struct ioport {
 struct ioport_operations {
bool (*io_in)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size);
bool (*io_out)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size);
-   void (*generate_fdt_node)(struct ioport *ioport, void *fdt,
- void (*generate_irq_prop)(void *fdt,
-   u8 irq,
-   enum irq_type));
 };
 
 void ioport__map_irq(u8 *irq);
diff --git a/ioport.c b/ioport.c
index a6972179..e0123f27 100644
--- a/ioport.c
+++ b/ioport.c
@@ -56,7 +56,6 @@ static struct ioport *ioport_get(struct rb_root *root, u64 
addr)
 /* Called with ioport_lock held. */
 static void ioport_unregister(struct rb_root *root, struct ioport *data)
 {
-   device__unregister(>dev_hdr);
ioport_remove(root, data);
free(data);
 }
@@ -70,30 +69,6 @@ static void ioport_put(struct rb_root *root, struct ioport 
*data)
mutex_unlock(_lock);
 }
 
-#ifdef CONFIG_HAS_LIBFDT
-static void generate_ioport_fdt_node(void *fdt,
-struct device_header *dev_hdr,
-void (*generate_irq_prop)(void *fdt,
-  u8 irq,
-  enum irq_type))
-{
-   struct ioport *ioport = container_of(dev_hdr, struct ioport, dev_hdr);
-   struct ioport_operations *ops = ioport->ops;
-
-   if (ops->generate_fdt_node)
-   ops->generate_fdt_node(ioport, fdt, generate_irq_prop);
-}
-#else
-static void generate_ioport_fdt_node(void *fdt,
-struct device_header *dev_hdr,
-void (*generate_irq_prop)(void *fdt,
-  u8 irq,
-  enum irq_type))
-{
-   die("Unable to generate device tree nodes without libfdt\n");
-}
-#endif
-
 int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops, 
int count, void *param)
 {
struct ioport *entry;
@@ -107,10 +82,6 @@ int ioport__register(struct kvm *kvm, u16 port, struct 
ioport_operations *ops, i
.node   = RB_INT_INIT(port, port + count),
.ops= ops,
.priv   = param,
-   .dev_hdr= (struct device_header) {
-   .bus_type   = DEVICE_BUS_IOPORT,
-   .data   = generate_ioport_fdt_node,
-   },
/*
 * Start from 0 because ioport__unregister() doesn't decrement
 * the reference count.
@@ -123,15 +94,10 @@ int ioport__register(struct kvm *kvm, u16 port, struct 
ioport_operations *ops, i
r = ioport_insert(_tree, entry);
if (r < 0)
goto out_free;
-   r = device__register(>dev_hdr);
-   if (r < 0)
-   goto out_remove;
mutex_unlock(_lock);
 
return port;
 
-out_remove:
-   ioport_remove(_tree, entry);
 out_free:
free(entry);
mutex_unlock(_lock);
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 01/22] ioport: Remove ioport__setup_arch()

2021-03-15 Thread Andre Przywara
Since x86 had a special need for registering tons of special I/O ports,
we had an ioport__setup_arch() callback, to allow each architecture
to do the same. As it turns out no one uses it beside x86, so we remove
that unnecessary abstraction.

The generic function was registered via a device_base_init() call, so
we just do the same for the x86 specific function only, and can remove
the unneeded ioport__setup_arch().

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 arm/ioport.c | 5 -
 include/kvm/ioport.h | 1 -
 ioport.c | 6 --
 mips/kvm.c   | 5 -
 powerpc/ioport.c | 6 --
 x86/ioport.c | 3 ++-
 6 files changed, 2 insertions(+), 24 deletions(-)

diff --git a/arm/ioport.c b/arm/ioport.c
index 2f0feb9a..24092c9d 100644
--- a/arm/ioport.c
+++ b/arm/ioport.c
@@ -1,11 +1,6 @@
 #include "kvm/ioport.h"
 #include "kvm/irq.h"
 
-int ioport__setup_arch(struct kvm *kvm)
-{
-   return 0;
-}
-
 void ioport__map_irq(u8 *irq)
 {
*irq = irq__alloc_line();
diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
index 039633f7..d0213541 100644
--- a/include/kvm/ioport.h
+++ b/include/kvm/ioport.h
@@ -35,7 +35,6 @@ struct ioport_operations {
enum irq_type));
 };
 
-int ioport__setup_arch(struct kvm *kvm);
 void ioport__map_irq(u8 *irq);
 
 int __must_check ioport__register(struct kvm *kvm, u16 port, struct 
ioport_operations *ops,
diff --git a/ioport.c b/ioport.c
index 844a832d..a6972179 100644
--- a/ioport.c
+++ b/ioport.c
@@ -221,12 +221,6 @@ out:
return !kvm->cfg.ioport_debug;
 }
 
-int ioport__init(struct kvm *kvm)
-{
-   return ioport__setup_arch(kvm);
-}
-dev_base_init(ioport__init);
-
 int ioport__exit(struct kvm *kvm)
 {
ioport__unregister_all();
diff --git a/mips/kvm.c b/mips/kvm.c
index 26355930..e110e5d5 100644
--- a/mips/kvm.c
+++ b/mips/kvm.c
@@ -100,11 +100,6 @@ void kvm__irq_trigger(struct kvm *kvm, int irq)
die_perror("KVM_IRQ_LINE ioctl");
 }
 
-int ioport__setup_arch(struct kvm *kvm)
-{
-   return 0;
-}
-
 bool kvm__arch_cpu_supports_vm(void)
 {
return true;
diff --git a/powerpc/ioport.c b/powerpc/ioport.c
index 0c188b61..a5cff4ee 100644
--- a/powerpc/ioport.c
+++ b/powerpc/ioport.c
@@ -12,12 +12,6 @@
 
 #include 
 
-int ioport__setup_arch(struct kvm *kvm)
-{
-   /* PPC has no legacy ioports to set up */
-   return 0;
-}
-
 void ioport__map_irq(u8 *irq)
 {
 }
diff --git a/x86/ioport.c b/x86/ioport.c
index 7ad7b8f3..a8d2bb1a 100644
--- a/x86/ioport.c
+++ b/x86/ioport.c
@@ -69,7 +69,7 @@ void ioport__map_irq(u8 *irq)
 {
 }
 
-int ioport__setup_arch(struct kvm *kvm)
+static int ioport__setup_arch(struct kvm *kvm)
 {
int r;
 
@@ -150,3 +150,4 @@ int ioport__setup_arch(struct kvm *kvm)
 
return 0;
 }
+dev_base_init(ioport__setup_arch);
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v3 02/22] hw/serial: Use device abstraction for FDT generator function

2021-03-15 Thread Andre Przywara
At the moment we use the .generate_fdt_node member of the ioport ops
structure to store the function pointer for the FDT node generator
function. ioport__register() will then put a wrapper and this pointer
into the device header.
The serial device is the only device making use of this special ioport
feature, so let's move this over to using the device header directly.

This will allow us to get rid of this .generate_fdt_node member in the
ops and simplify the code.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/serial.c   | 49 +--
 include/kvm/kvm.h |  2 ++
 2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/hw/serial.c b/hw/serial.c
index 13c4663e..b0465d99 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -23,6 +23,7 @@
 #define UART_IIR_TYPE_BITS 0xc0
 
 struct serial8250_device {
+   struct device_headerdev_hdr;
struct mutexmutex;
u8  id;
 
@@ -53,9 +54,20 @@ struct serial8250_device {
.msr= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS, \
.mcr= UART_MCR_OUT2,
 
+#ifdef CONFIG_HAS_LIBFDT
+static
+void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
+ fdt_irq_fn irq_fn);
+#else
+#define serial8250_generate_fdt_node   NULL
+#endif
 static struct serial8250_device devices[] = {
/* ttyS0 */
[0] = {
+   .dev_hdr = {
+   .bus_type   = DEVICE_BUS_IOPORT,
+   .data   = serial8250_generate_fdt_node,
+   },
.mutex  = MUTEX_INITIALIZER,
 
.id = 0,
@@ -66,6 +78,10 @@ static struct serial8250_device devices[] = {
},
/* ttyS1 */
[1] = {
+   .dev_hdr = {
+   .bus_type   = DEVICE_BUS_IOPORT,
+   .data   = serial8250_generate_fdt_node,
+   },
.mutex  = MUTEX_INITIALIZER,
 
.id = 1,
@@ -76,6 +92,10 @@ static struct serial8250_device devices[] = {
},
/* ttyS2 */
[2] = {
+   .dev_hdr = {
+   .bus_type   = DEVICE_BUS_IOPORT,
+   .data   = serial8250_generate_fdt_node,
+   },
.mutex  = MUTEX_INITIALIZER,
 
.id = 2,
@@ -86,6 +106,10 @@ static struct serial8250_device devices[] = {
},
/* ttyS3 */
[3] = {
+   .dev_hdr = {
+   .bus_type   = DEVICE_BUS_IOPORT,
+   .data   = serial8250_generate_fdt_node,
+   },
.mutex  = MUTEX_INITIALIZER,
 
.id = 3,
@@ -371,13 +395,14 @@ char *fdt_stdout_path = NULL;
 
 #define DEVICE_NAME_MAX_LEN 32
 static
-void serial8250_generate_fdt_node(struct ioport *ioport, void *fdt,
- void (*generate_irq_prop)(void *fdt,
-   u8 irq,
-   enum irq_type))
+void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
+ fdt_irq_fn irq_fn)
 {
char dev_name[DEVICE_NAME_MAX_LEN];
-   struct serial8250_device *dev = ioport->priv;
+   struct serial8250_device *dev = container_of(dev_hdr,
+struct serial8250_device,
+dev_hdr);
+
u64 addr = KVM_IOPORT_AREA + dev->iobase;
u64 reg_prop[] = {
cpu_to_fdt64(addr),
@@ -395,24 +420,26 @@ void serial8250_generate_fdt_node(struct ioport *ioport, 
void *fdt,
_FDT(fdt_begin_node(fdt, dev_name));
_FDT(fdt_property_string(fdt, "compatible", "ns16550a"));
_FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop)));
-   generate_irq_prop(fdt, dev->irq, IRQ_TYPE_LEVEL_HIGH);
+   irq_fn(fdt, dev->irq, IRQ_TYPE_LEVEL_HIGH);
_FDT(fdt_property_cell(fdt, "clock-frequency", 1843200));
_FDT(fdt_end_node(fdt));
 }
-#else
-#define serial8250_generate_fdt_node   NULL
 #endif
 
 static struct ioport_operations serial8250_ops = {
.io_in  = serial8250_in,
.io_out = serial8250_out,
-   .generate_fdt_node  = serial8250_generate_fdt_node,
 };
 
-static int serial8250__device_init(struct kvm *kvm, struct serial8250_device 
*dev)
+static int serial8250__device_init(struct kvm *kvm,
+  struct serial8250_device *dev)
 {
int r;
 
+   r = device__register(&g

[PATCH kvmtool v3 00/22] Unify I/O port and MMIO trap handling

2021-03-15 Thread Andre Przywara
Hi,

this version is addressing Alexandru's comments, fixing mostly minor
issues in the naming scheme. The biggest change is to keep the
ioport__read/ioport_write wrappers for the serial device.
For more details see the changelog below.
==

At the moment we use two separate code paths to handle exits for
KVM_EXIT_IO (ioport.c) and KVM_EXIT_MMIO (mmio.c), even though they
are semantically very similar. Because the trap handler callback routine
is different, devices need to decide on one conduit or need to provide
different handler functions for both of them.

This is not only unnecessary code duplication, but makes switching
devices from I/O port to MMIO a tedious task, even though there is no
real difference between the two, especially on ARM and PowerPC.

For ARM we aim at providing a flexible memory layout, and also have
trouble with the UART and RTC device overlapping with the PCI I/O area,
so it seems indicated to tackle this once and for all.

The first three patches do some cleanup, to simplify things later.

Patch 04/22 lays the groundwork, by extending mmio.c to be able to also
register I/O port trap handlers, using the same callback prototype as
we use for MMIO.

The next 14 patches then convert devices that use the I/O port
interface over to the new joint interface. This requires to rework
the trap handler routine to adhere to the same prototype as the existing
MMIO handlers. For most devices this is done in two steps: a first to
introduce the reworked handler routine, and a second to switch to the new
joint registration routine. For some devices the first step is trivial,
so it's done in one patch.

Patch 19/22 then retires the old I/O port interface, by removing ioport.c
and friends.
Patch 20/22 uses the opportunity to clean up the memory map description,
also declares a new region (from 16MB on), where the final two patches
switch the UART and the RTC device to. They are now registered
on the MMIO "bus", when running on ARM or arm64. This moves them away
from the first 64KB, so they are not in the PCI I/O area anymore.

Please have a look and comment!

Cheers,
Andre

Changelog v2 .. v3:
- use _io as function prefix for x86 I/O port devices
- retain ioport__{read,write}8() wrappers for serial device
- fix memory map ASCII art
- fix serial base declaration
- minor nit fixes
- add Reviewed-by: tags

Changelog v1 .. v2:
- rework memory map definition
- add explicit debug output for debug I/O port
- add explicit check for MMIO coalescing on I/O ports
- drop usage of ioport__{read,write}8() from serial
- drop explicit I/O port cleanup routine (to mimic MMIO operation)
- add comment for IOTRAP_BUS_MASK
- minor cleanups / formatting changes


Andre Przywara (22):
  ioport: Remove ioport__setup_arch()
  hw/serial: Use device abstraction for FDT generator function
  ioport: Retire .generate_fdt_node functionality
  mmio: Extend handling to include ioport emulation
  hw/i8042: Clean up data types
  hw/i8042: Refactor trap handler
  hw/i8042: Switch to new trap handlers
  x86/ioport: Refactor trap handlers
  x86/ioport: Switch to new trap handlers
  hw/rtc: Refactor trap handlers
  hw/rtc: Switch to new trap handler
  hw/vesa: Switch trap handling to use MMIO handler
  hw/serial: Refactor trap handler
  hw/serial: Switch to new trap handlers
  vfio: Refactor ioport trap handler
  vfio: Switch to new ioport trap handlers
  virtio: Switch trap handling to use MMIO handler
  pci: Switch trap handling to use MMIO handler
  Remove ioport specific routines
  arm: Reorganise and document memory map
  hw/serial: ARM/arm64: Use MMIO at higher addresses
  hw/rtc: ARM/arm64: Use MMIO at higher addresses

 Makefile  |   1 -
 arm/include/arm-common/kvm-arch.h |  47 --
 arm/ioport.c  |   5 -
 hw/i8042.c|  94 +---
 hw/rtc.c  |  91 ++--
 hw/serial.c   | 126 +++-
 hw/vesa.c |  19 +--
 include/kvm/i8042.h   |   1 -
 include/kvm/ioport.h  |  32 
 include/kvm/kvm.h |  49 ++-
 ioport.c  | 235 --
 mips/kvm.c|   5 -
 mmio.c|  65 +++--
 pci.c |  82 +++
 powerpc/ioport.c  |   6 -
 vfio/core.c   |  50 ---
 virtio/pci.c  |  46 ++
 x86/ioport.c  | 108 +++---
 18 files changed, 421 insertions(+), 641 deletions(-)
 delete mode 100644 ioport.c

-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH kvmtool v2 21/22] hw/serial: ARM/arm64: Use MMIO at higher addresses

2021-03-15 Thread Andre Przywara
On Tue, 9 Mar 2021 16:02:20 +
Alexandru Elisei  wrote:

> Hi Andre,
> 
> I think you forgot to change the way the address is generated in
> serial8250_generate_fdt_node, it's still KVM_IOPORT_AREA + dev->iobase. It's
> technically correct, as KVM_IOPORT_AREA == ARM_IOPORT_AREA == 0x0, but very
> confusing (and prone to breakage is something changes in the memory layout).

So I moved the addition of KVM_IOPORT_AREA into the definition of
serial_iobase() (at the beginning of the file). This means I can remove
it below, and just use dev->iobase as is.

> One more comment below.
> 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > Using the UART devices at their legacy I/O addresses as set by IBM in
> > 1981 was a kludge we used for simplicity on ARM platforms as well.
> > However this imposes problems due to their missing alignment and overlap
> > with the PCI I/O address space.
> >
> > Now that we can switch a device easily between using ioports and MMIO,
> > let's move the UARTs out of the first 4K of memory on ARM platforms.
> >
> > That should be transparent for well behaved guests, since the change is
> > naturally reflected in the device tree. Even "earlycon" keeps working,
> > as the stdout-path property is adjusted automatically.
> >
> > People providing direct earlycon parameters via the command line need to
> > adjust it to: "earlycon=uart,mmio,0x100".
> >
> > Signed-off-by: Andre Przywara 
> > ---
> >  arm/include/arm-common/kvm-arch.h |  3 +++
> >  hw/serial.c   | 45 ---
> >  2 files changed, 32 insertions(+), 16 deletions(-)
> >
> > diff --git a/arm/include/arm-common/kvm-arch.h 
> > b/arm/include/arm-common/kvm-arch.h
> > index b12255b0..633ea8fa 100644
> > --- a/arm/include/arm-common/kvm-arch.h
> > +++ b/arm/include/arm-common/kvm-arch.h
> > @@ -28,6 +28,9 @@
> >  #define ARM_IOPORT_SIZE(1U << 16)
> >  
> >  
> > +#define ARM_UART_MMIO_BASE ARM_MMIO_AREA
> > +#define ARM_UART_MMIO_SIZE 0x1
> > +
> >  #define KVM_FLASH_MMIO_BASE(ARM_MMIO_AREA + 0x100)
> >  #define KVM_FLASH_MAX_SIZE 0x100
> >  
> > diff --git a/hw/serial.c b/hw/serial.c
> > index 4be188a1..1854add2 100644
> > --- a/hw/serial.c
> > +++ b/hw/serial.c
> > @@ -13,6 +13,17 @@
> >  
> >  #include 
> >  
> > +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
> > +#define serial_iobase(nr)  (ARM_UART_MMIO_BASE + (nr) * 0x1000)
> > +#define serial_irq(nr) (32 + (nr))
> > +#define SERIAL8250_BUS_TYPEDEVICE_BUS_MMIO
> > +#else
> > +#define serial_iobase(nr)  nr) & 1) ? 0x200 : 0x300) + \
> > +((nr) >= 2 ? 0xe8 : 0xf8))
> > +#define serial_irq(nr) (((nr) & 1) ? 3 : 4)  
> 
> Those two defines are hard to read, is there a reason for changing them from 
> v1?
> They looked a lot more readable in v1.

Oh, good catch, must have been a rebase artefact, from the very first
draft version I had. Fixed that.

Cheers,
Andre

> 
> > +#define SERIAL8250_BUS_TYPEDEVICE_BUS_IOPORT
> > +#endif
> > +
> >  /*
> >   * This fakes a U6_16550A. The fifo len needs to be 64 as the kernel
> >   * expects that for autodetection.
> > @@ -27,7 +38,7 @@ struct serial8250_device {
> > struct mutexmutex;
> > u8  id;
> >  
> > -   u16 iobase;
> > +   u32 iobase;
> > u8  irq;
> > u8  irq_state;
> > int txcnt;
> > @@ -65,56 +76,56 @@ static struct serial8250_device devices[] = {
> > /* ttyS0 */
> > [0] = {
> > .dev_hdr = {
> > -   .bus_type   = DEVICE_BUS_IOPORT,
> > +   .bus_type   = SERIAL8250_BUS_TYPE,
> > .data   = serial8250_generate_fdt_node,
> > },
> > .mutex  = MUTEX_INITIALIZER,
> >  
> > .id = 0,
> > -   .iobase = 0x3f8,
> > -   .irq= 4,
> > +   .iobase = serial_iobase(0),
> > +   .irq= serial_irq(0),
> >  
> > SERIAL_REGS_SETTING
> > },
> > /* ttyS1 */
> > [1] = {
> > .dev_hdr = {
> > -   .bus_type   

Re: [PATCH kvmtool v2 20/22] arm: Reorganise and document memory map

2021-03-15 Thread Andre Przywara
On Tue, 9 Mar 2021 15:46:29 +
Alexandru Elisei  wrote:

Hi,

> Hi Andre,
> 
> This is a really good idea, thank you for implementing it!
> 
> Some comments below.
> 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > The hardcoded memory map we expose to a guest is currently described
> > using a series of partially interconnected preprocessor constants,
> > which is hard to read and follow.
> >
> > In preparation for moving the UART and RTC to some different MMIO
> > region, document the current map with some ASCII art, and clean up the
> > definition of the sections.
> >
> > No functional change.
> >
> > Signed-off-by: Andre Przywara 
> > ---
> >  arm/include/arm-common/kvm-arch.h | 41 ++-
> >  1 file changed, 29 insertions(+), 12 deletions(-)
> >
> > diff --git a/arm/include/arm-common/kvm-arch.h 
> > b/arm/include/arm-common/kvm-arch.h
> > index d84e50cd..b12255b0 100644
> > --- a/arm/include/arm-common/kvm-arch.h
> > +++ b/arm/include/arm-common/kvm-arch.h
> > @@ -7,14 +7,33 @@
> >  
> >  #include "arm-common/gic.h"
> >  
> > +/*
> > + * The memory map used for ARM guests (not to scale):
> > + *
> > + * 0  64K  16M 32M 48M1GB   2GB
> > + * +---+-..-+---+---+----+-+--.--+---..
> > + * | (PCI) || int.  |   || | |
> > + * |  I/O  || MMIO: | Flash | virtio | GIC |   PCI   |  DRAM
> > + * | ports || UART, |   |  MMIO  | |  (AXI)  |
> > + * |   || RTC   |   || | |
> > + * +---+-..-+---+---+----+-+--.--+---..
> > + */  
> 
> Nitpick: I searched the PCI Local Bus Specification revision 3.0 (which 
> kvmtool
> currently implements) for the term I/O ports, and found one mention in a 
> schematic
> for an add-in card. The I/O region is called in the spec I/O Space.

Right, will change that.
 
> I don't know what "int." means in the region for the UART and RTC.

It was meant to mean "internal", but this is really nonsensical, so I
will replace it with "plat MMIO".
 
> The comment says that the art is not to scale, so I don't think there's any 
> need
> for the "..." between the corners of the regions. To my eyes, it makes the 
> ASCII
> art look crooked.

fixed.
 
> The next patches add the UART and RTC outside the first 64K, I think the 
> region
> should be documented in the patches where the changes are made, not here. 
> Another
> alternative would be to move this patch to the end of the series instead of
> incrementally changing the memory ASCII art (which I imagine is time 
> consuming).

You passed the scrutiny test ;-)
I noticed this last minute, but didn't feel like changing it then.
Have done it now.

> 
> Otherwise, the numbers look OK.
> 
> > +
> >  #define ARM_IOPORT_AREA_AC(0x, UL)
> > -#define ARM_FLASH_AREA _AC(0x0200, UL)
> > -#define ARM_MMIO_AREA  _AC(0x0300, UL)
> > +#define ARM_MMIO_AREA  _AC(0x0100, UL)  
> 
> The patch says it is *documenting* the memory layout, but here it is 
> *changing*
> the layout. Other than that, I like the shuffling of definitions so the 
> kvmtool
> global defines are closer to the arch values.

I amended the commit message to mention that I change the value of
ARM_MMIO_AREA, but that stays internal to that file and doesn't affect
the other definitions.
In fact I imported this header into a C file and printed all
externally used names, before and after: it didn't show any changes.

Cheers,
Andre

> >  #define ARM_AXI_AREA   _AC(0x4000, UL)
> >  #define ARM_MEMORY_AREA_AC(0x8000, UL)
> >  
> > -#define ARM_LOMAP_MAX_MEMORY   ((1ULL << 32) - ARM_MEMORY_AREA)
> > -#define ARM_HIMAP_MAX_MEMORY   ((1ULL << 40) - ARM_MEMORY_AREA)
> > +#define KVM_IOPORT_AREAARM_IOPORT_AREA
> > +#define ARM_IOPORT_SIZE(1U << 16)
> > +
> > +
> > +#define KVM_FLASH_MMIO_BASE(ARM_MMIO_AREA + 0x100)
> > +#define KVM_FLASH_MAX_SIZE 0x100
> > +
> > +#define KVM_VIRTIO_MMIO_AREA   (KVM_FLASH_MMIO_BASE + 
> > KVM_FLASH_MAX_SIZE)
> > +#define ARM_VIRTIO_MMIO_SIZE   (ARM_AXI_AREA - \
> > +   (KVM_VIRTIO_MMIO_AREA + ARM_GIC_SIZE))
> >  
> >  #define ARM_GIC_DIST_BASE  (ARM_AXI_AREA - ARM_GIC_DIST_SIZE)
> >  #define ARM_GIC_CPUI_BASE  (ARM_GIC_DIST_BASE - ARM_GIC_CPU

Re: [PATCH kvmtool v2 13/22] hw/serial: Refactor trap handler

2021-03-15 Thread Andre Przywara
On Fri, 12 Mar 2021 11:29:43 +
Alexandru Elisei  wrote:

> Hi Andre,
> 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > With the planned retirement of the special ioport emulation code, we
> > need to provide an emulation function compatible with the MMIO prototype.
> >
> > Adjust the trap handler to use that new function, and provide shims to
> > implement the old ioport interface, for now.
> >
> > We drop the usage of ioport__read8/write8 entirely, as this would only
> > be applicable for I/O port accesses, and does nothing for 8-bit wide
> > accesses anyway.
> >
> > Signed-off-by: Andre Przywara 
> > ---
> >  hw/serial.c | 93 +
> >  1 file changed, 58 insertions(+), 35 deletions(-)
> >
> > diff --git a/hw/serial.c b/hw/serial.c
> > index b0465d99..c495eac1 100644
> > --- a/hw/serial.c
> > +++ b/hw/serial.c
> > @@ -242,36 +242,31 @@ void serial8250__inject_sysrq(struct kvm *kvm, char 
> > sysrq)
> > sysrq_pending = sysrq;
> >  }
> >  
> > -static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
> > u16 port,
> > -  void *data, int size)
> > +static bool serial8250_out(struct serial8250_device *dev, struct kvm_cpu 
> > *vcpu,
> > +  u16 offset, u8 data)
> >  {
> > -   struct serial8250_device *dev = ioport->priv;
> > -   u16 offset;
> > bool ret = true;
> > -   char *addr = data;
> >  
> > mutex_lock(>mutex);
> >  
> > -   offset = port - dev->iobase;
> > -
> > switch (offset) {
> > case UART_TX:
> > if (dev->lcr & UART_LCR_DLAB) {
> > -   dev->dll = ioport__read8(data);
> > +   dev->dll = data;
> > break;
> > }
> >  
> > /* Loopback mode */
> > if (dev->mcr & UART_MCR_LOOP) {
> > if (dev->rxcnt < FIFO_LEN) {
> > -   dev->rxbuf[dev->rxcnt++] = *addr;
> > +   dev->rxbuf[dev->rxcnt++] = data;
> > dev->lsr |= UART_LSR_DR;
> > }
> > break;
> > }
> >  
> > if (dev->txcnt < FIFO_LEN) {
> > -   dev->txbuf[dev->txcnt++] = *addr;
> > +   dev->txbuf[dev->txcnt++] = data;
> > dev->lsr &= ~UART_LSR_TEMT;
> > if (dev->txcnt == FIFO_LEN / 2)
> > dev->lsr &= ~UART_LSR_THRE;
> > @@ -283,18 +278,18 @@ static bool serial8250_out(struct ioport *ioport, 
> > struct kvm_cpu *vcpu, u16 port
> > break;
> > case UART_IER:
> > if (!(dev->lcr & UART_LCR_DLAB))
> > -   dev->ier = ioport__read8(data) & 0x0f;
> > +   dev->ier = data & 0x0f;
> > else
> > -   dev->dlm = ioport__read8(data);
> > +   dev->dlm = data;
> > break;
> > case UART_FCR:
> > -   dev->fcr = ioport__read8(data);
> > +   dev->fcr = data;
> > break;
> > case UART_LCR:
> > -   dev->lcr = ioport__read8(data);
> > +   dev->lcr = data;
> > break;
> > case UART_MCR:
> > -   dev->mcr = ioport__read8(data);
> > +   dev->mcr = data;
> > break;
> > case UART_LSR:
> > /* Factory test */
> > @@ -303,7 +298,7 @@ static bool serial8250_out(struct ioport *ioport, 
> > struct kvm_cpu *vcpu, u16 port
> > /* Not used */
> > break;
> > case UART_SCR:
> > -   dev->scr = ioport__read8(data);
> > +   dev->scr = data;
> > break;
> > default:
> > ret = false;
> > @@ -317,7 +312,7 @@ static bool serial8250_out(struct ioport *ioport, 
> > struct kvm_cpu *vcpu, u16 port
> > return ret;
> >  }
> >  
> > -static void serial8250_rx(struct serial8250_device *dev, void *data)
> > +static void serial8250_rx(struct serial8250_device *dev, u8 *data)
> >  {
> > if (dev->rxdone == dev->rxcnt)
> > return;
> > @@ -325,57 +320,54 @@ static void serial8250_rx(struct serial8250_device 
> > *dev, void *d

Re: [PATCH kvmtool v2 09/22] x86/ioport: Switch to new trap handlers

2021-03-15 Thread Andre Przywara
On Tue, 9 Mar 2021 12:09:52 +
Alexandru Elisei  wrote:

> Hi Andre,
> 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > Now that the x86 I/O ports have trap handlers adhering to the MMIO fault
> > handler prototype, let's switch over to the joint registration routine.
> >
> > This allows us to get rid of the ioport shim routines.
> >
> > Since the debug output was done in ioport.c, we would lose this
> > functionality when moving over to the MMIO handlers. So bring this back
> > here explicitly, by introducing debug_mmio().
> >
> > Signed-off-by: Andre Przywara 
> > ---
> >  x86/ioport.c | 102 +++
> >  1 file changed, 37 insertions(+), 65 deletions(-)
> >
> > diff --git a/x86/ioport.c b/x86/ioport.c
> > index 78f9a863..9fcbb6c9 100644
> > --- a/x86/ioport.c
> > +++ b/x86/ioport.c
> > @@ -3,21 +3,35 @@
> >  #include 
> >  #include 
> >  
> > -static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> > +static void debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> >u8 is_write, void *ptr)  
> 
> Since the function is about ioports (it even checks cfg.ioport_debug), 
> shouldn't
> something like debug_io/debug_pio/debug_ioport/ related> be
> more appropriate?

Yes, I changed the function to debug_io(), to be in line with the other
functions and the names in the other devices.

> Otherwise looks good: the only emulation callback that could fail was
> debug_ops->debug_io_out, which triggered a print if cfg.ioport_debug was set, 
> and
> the callback is replaced by debug_mmio. With the name change:
> 
> Reviewed-by: Alexandru Elisei 

Thanks!

Andre

> >  {
> > +   if (!vcpu->kvm->cfg.ioport_debug)
> > +   return;
> > +
> > +   fprintf(stderr, "debug port %s from VCPU%lu: port=0x%lx, size=%u",
> > +   is_write ? "write" : "read", vcpu->cpu_id,
> > +   (unsigned long)addr, len);
> > +   if (is_write) {
> > +   u32 value;
> > +
> > +   switch (len) {
> > +   case 1: value = ioport__read8(data); break;
> > +   case 2: value = ioport__read16((u16*)data); break;
> > +   case 4: value = ioport__read32((u32*)data); break;
> > +   default: value = 0; break;
> > +   }
> > +   fprintf(stderr, ", data: 0x%x\n", value);
> > +   } else {
> > +   fprintf(stderr, "\n");
> > +   }
> >  }
> >  
> > -static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
> > port, void *data, int size)
> > +static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> > +  u8 is_write, void *ptr)
> >  {
> > -   dummy_mmio(vcpu, port, data, size, true, NULL);
> > -   return 0;
> >  }
> >  
> > -static struct ioport_operations debug_ops = {
> > -   .io_out = debug_io_out,
> > -};
> > -
> >  static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> >u32 len, u8 is_write, void *ptr)
> >  {
> > @@ -31,37 +45,6 @@ static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 
> > addr, u8 *data,
> > putchar(ch);
> >  }
> >  
> > -static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu 
> > *vcpu, u16 port, void *data, int size)
> > -{
> > -   seabios_debug_mmio(vcpu, port, data, size, true, NULL);
> > -   return 0;
> > -}
> > -
> > -static struct ioport_operations seabios_debug_ops = {
> > -   .io_out = seabios_debug_io_out,
> > -};
> > -
> > -static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
> > port, void *data, int size)
> > -{
> > -   dummy_mmio(vcpu, port, data, size, false, NULL);
> > -   return true;
> > -}
> > -
> > -static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
> > port, void *data, int size)
> > -{
> > -   dummy_mmio(vcpu, port, data, size, true, NULL);
> > -   return true;
> > -}
> > -
> > -static struct ioport_operations dummy_read_write_ioport_ops = {
> > -   .io_in  = dummy_io_in,
> > -   .io_out = dummy_io_out,
> > -};
> > -
> > -static struct ioport_operations dummy_write_only_ioport_ops = {
> > -   .io_out = dummy_io_out,
> > -};
> > -
> >  /*
> >   * The "fast A20 gate"
> >   */
> > @@ -

Re: [PATCH kvmtool v2 08/22] x86/ioport: Refactor trap handlers

2021-03-15 Thread Andre Przywara
On Tue, 9 Mar 2021 11:49:47 +
Alexandru Elisei  wrote:

> Hi Andre,
> 
> Regarding the naming of the functions, these are real ioport emulation 
> functions,
> which are executed because a KVM_EXIT_IO exit reason from KVM_RUN. Wouldn't 
> naming
> the functions something like *_pio or *_io be more appropriate?

Yes, indeed these devices here are per definition pure port I/O
devices. I changed the names to _io, to be in line with the later
patches.

Cheers,
Andre
 
> On 2/25/21 12:59 AM, Andre Przywara wrote:
> > With the planned retirement of the special ioport emulation code, we
> > need to provide emulation functions compatible with the MMIO
> > prototype.
> >
> > Adjust the trap handlers to use that new function, and provide shims to
> > implement the old ioport interface, for now.
> >
> > Signed-off-by: Andre Przywara 
> > Reviewed-by: Alexandru Elisei 
> > ---
> >  x86/ioport.c | 30 ++
> >  1 file changed, 26 insertions(+), 4 deletions(-)
> >
> > diff --git a/x86/ioport.c b/x86/ioport.c
> > index a8d2bb1a..78f9a863 100644
> > --- a/x86/ioport.c
> > +++ b/x86/ioport.c
> > @@ -3,8 +3,14 @@
> >  #include 
> >  #include 
> >  
> > +static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
> > +  u8 is_write, void *ptr)
> > +{
> > +}
> > +
> >  static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
> > port, void *data, int size)
> >  {
> > +   dummy_mmio(vcpu, port, data, size, true, NULL);
> > return 0;
> >  }
> >  
> > @@ -12,15 +18,23 @@ static struct ioport_operations debug_ops = {
> > .io_out = debug_io_out,
> >  };
> >  
> > -static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu 
> > *vcpu, u16 port, void *data, int size)
> > +static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> > +  u32 len, u8 is_write, void *ptr)
> >  {
> > char ch;
> >  
> > +   if (!is_write)
> > +   return;
> > +
> > ch = ioport__read8(data);
> >  
> > putchar(ch);
> > +}
> >  
> > -   return true;
> > +static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu 
> > *vcpu, u16 port, void *data, int size)
> > +{
> > +   seabios_debug_mmio(vcpu, port, data, size, true, NULL);
> > +   return 0;
> >  }
> >  
> >  static struct ioport_operations seabios_debug_ops = {
> > @@ -29,11 +43,13 @@ static struct ioport_operations seabios_debug_ops = {
> >  
> >  static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
> > port, void *data, int size)
> >  {
> > +   dummy_mmio(vcpu, port, data, size, false, NULL);
> > return true;
> >  }
> >  
> >  static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
> > port, void *data, int size)
> >  {
> > +   dummy_mmio(vcpu, port, data, size, true, NULL);
> > return true;
> >  }
> >  
> > @@ -50,13 +66,19 @@ static struct ioport_operations 
> > dummy_write_only_ioport_ops = {
> >   * The "fast A20 gate"
> >   */
> >  
> > -static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu 
> > *vcpu, u16 port, void *data, int size)
> > +static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 
> > len,
> > +u8 is_write, void *ptr)
> >  {
> > /*
> >  * A20 is always enabled.
> >  */
> > -   ioport__write8(data, 0x02);
> > +   if (!is_write)
> > +   ioport__write8(data, 0x02);
> > +}
> >  
> > +static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu 
> > *vcpu, u16 port, void *data, int size)
> > +{
> > +   ps2_control_mmio(vcpu, port, data, size, false, NULL);
> > return true;
> >  }
> >

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH kvmtool v2 04/22] mmio: Extend handling to include ioport emulation

2021-03-15 Thread Andre Przywara
On Wed, 3 Mar 2021 17:58:29 +
Alexandru Elisei  wrote:

Hi Alex,

> On 2/25/21 12:58 AM, Andre Przywara wrote:
> > In their core functionality MMIO and I/O port traps are not really
> > different, yet we still have two totally separate code paths for
> > handling them. Devices need to decide on one conduit or need to provide
> > different handler functions for each of them.
> >
> > Extend the existing MMIO emulation to also cover ioport handlers.
> > This just adds another RB tree root for holding the I/O port handlers,
> > but otherwise uses the same tree population and lookup code.
> > "ioport" or "mmio" just become a flag in the registration function.
> > Provide wrappers to not break existing users, and allow an easy
> > transition for the existing ioport handlers.
> >
> > This also means that ioport handlers now can use the same emulation
> > callback prototype as MMIO handlers, which means we have to migrate them
> > over. To allow a smooth transition, we hook up the new I/O emulate
> > function to the end of the existing ioport emulation code.
> >
> > Signed-off-by: Andre Przywara 
> > ---
> >  include/kvm/kvm.h | 49 ---
> >  ioport.c  |  4 +--
> >  mmio.c| 65 +++
> >  3 files changed, 102 insertions(+), 16 deletions(-)
> >
> > diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
> > index f1f0afd7..306b258a 100644
> > --- a/include/kvm/kvm.h
> > +++ b/include/kvm/kvm.h
> > @@ -27,10 +27,23 @@
> >  #define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
> >  #endif
> >  
> > +/*
> > + * We are reusing the existing DEVICE_BUS_MMIO and DEVICE_BUS_IOPORT 
> > constants
> > + * from kvm/devices.h to differentiate between registering an I/O port and 
> > an
> > + * MMIO region.
> > + * To avoid collisions with future additions of more bus types, we reserve
> > + * a generous 4 bits for the bus mask here.
> > + */
> > +#define IOTRAP_BUS_MASK0xf
> > +#define IOTRAP_COALESCE(1U << 4)
> > +
> >  #define DEFINE_KVM_EXT(ext)\
> > .name = #ext,   \
> > .code = ext
> >  
> > +struct kvm_cpu;
> > +typedef void (*mmio_handler_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data,
> > +   u32 len, u8 is_write, void *ptr);
> >  typedef void (*fdt_irq_fn)(void *fdt, u8 irq, enum irq_type irq_type);
> >  
> >  enum {
> > @@ -113,6 +126,8 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
> >  void kvm__irq_trigger(struct kvm *kvm, int irq);
> >  bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int 
> > direction, int size, u32 count);
> >  bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 
> > len, u8 is_write);
> > +bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
> > + int direction, int size, u32 count);
> >  int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void 
> > *userspace_addr);
> >  int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void 
> > *userspace_addr,
> >   enum kvm_mem_type type);
> > @@ -136,10 +151,36 @@ static inline int kvm__reserve_mem(struct kvm *kvm, 
> > u64 guest_phys, u64 size)
> >  KVM_MEM_TYPE_RESERVED);
> >  }
> >  
> > -int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 
> > phys_addr_len, bool coalesce,
> > -   void (*mmio_fn)(struct kvm_cpu *vcpu, u64 
> > addr, u8 *data, u32 len, u8 is_write, void *ptr),
> > -   void *ptr);
> > -bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
> > +int __must_check kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 
> > len,
> > + mmio_handler_fn mmio_fn, void *ptr,
> > + unsigned int flags);
> > +
> > +static inline
> > +int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr,
> > +   u64 phys_addr_len, bool coalesce,
> > +   mmio_handler_fn mmio_fn, void *ptr)
> > +{
> > +   return kvm__register_iotrap(kvm, phys_addr, phys_addr_len, mmio_fn, ptr,
> > +   DEVICE_BUS_MMIO | (coalesce ? IOTRAP_COALESCE : 0));
> > +}
> > +static inline
> > +int __must_check kvm__register_pio(struct kvm *kvm, u16 port, u16 len,
> 

Re: [kvm-unit-tests PATCH 2/6] arm/arm64: Remove dcache_line_size global variable

2021-03-04 Thread Andre Przywara
On Sat, 27 Feb 2021 10:41:57 +
Alexandru Elisei  wrote:

> Compute the dcache line size when doing dcache maintenance instead of using
> a global variable computed in setup(), which allows us to do dcache
> maintenance at any point in the boot process. This will be useful for
> running as an EFI app and it also aligns our implementation to that of the
> Linux kernel.

Can you add that this changes the semantic of dcache_by_line_op to use
the size instead of the end address?

> 
> For consistency, the arm code has been similary modified.
> 
> Signed-off-by: Alexandru Elisei 
> ---
>  lib/arm/asm/assembler.h   | 44 
>  lib/arm/asm/processor.h   |  7 --
>  lib/arm64/asm/assembler.h | 53 +++
>  lib/arm64/asm/processor.h |  7 --
>  lib/arm/setup.c   |  7 --
>  arm/cstart.S  | 18 +++--
>  arm/cstart64.S| 16 ++--
>  7 files changed, 102 insertions(+), 50 deletions(-)
>  create mode 100644 lib/arm/asm/assembler.h
>  create mode 100644 lib/arm64/asm/assembler.h
> 
> diff --git a/lib/arm/asm/assembler.h b/lib/arm/asm/assembler.h
> new file mode 100644
> index ..6b932df86204
> --- /dev/null
> +++ b/lib/arm/asm/assembler.h
> @@ -0,0 +1,44 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Based on several files from Linux version v5.10: 
> arch/arm/mm/proc-macros.S,
> + * arch/arm/mm/proc-v7.S.
> + */
> +
> +/*
> + * dcache_line_size - get the minimum D-cache line size from the CTR register
`> + * on ARMv7.
> + */
> + .macro  dcache_line_size, reg, tmp
> + mrc p15, 0, \tmp, c0, c0, 1 // read ctr
> + lsr \tmp, \tmp, #16
> + and \tmp, \tmp, #0xf// cache line size encoding
> + mov \reg, #4// bytes per word
> + mov \reg, \reg, lsl \tmp// actual cache line size
> + .endm
> +
> +/*
> + * Macro to perform a data cache maintenance for the interval
> + * [addr, addr + size).
> + *
> + *   op: operation to execute
> + *   domain  domain used in the dsb instruction
> + *   addr:   starting virtual address of the region
> + *   size:   size of the region
> + *   Corrupts:   addr, size, tmp1, tmp2
> + */
> + .macro dcache_by_line_op op, domain, addr, size, tmp1, tmp2
> + dcache_line_size \tmp1, \tmp2
> + add \size, \addr, \size
> + sub \tmp2, \tmp1, #1
> + bic \addr, \addr, \tmp2

Just a nit, but since my brain was in assembly land: We could skip tmp2,
by adding back #1 to tmp1 after the bic.
Same for the arm64 code.

> +9998:
> + .ifc\op, dccimvac
> + mcr p15, 0, \addr, c7, c14, 1
> + .else
> + .err
> + .endif
> + add \addr, \addr, \tmp1
> + cmp \addr, \size
> + blo 9998b
> + dsb \domain
> + .endm
> diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
> index 273366d1fe1c..3c36eac903f0 100644
> --- a/lib/arm/asm/processor.h
> +++ b/lib/arm/asm/processor.h
> @@ -9,11 +9,6 @@
>  #include 
>  #include 

Do we want the same protection against inclusion from C here as in the
arm64 version?

> -#define CTR_DMINLINE_SHIFT   16
> -#define CTR_DMINLINE_MASK(0xf << 16)
> -#define CTR_DMINLINE(x)  \
> - (((x) & CTR_DMINLINE_MASK) >> CTR_DMINLINE_SHIFT)
> -
>  enum vector {
>   EXCPTN_RST,
>   EXCPTN_UND,
> @@ -89,6 +84,4 @@ static inline u32 get_ctr(void)
>   return read_sysreg(CTR);
>  }
>  
> -extern unsigned long dcache_line_size;
> -
>  #endif /* _ASMARM_PROCESSOR_H_ */
> diff --git a/lib/arm64/asm/assembler.h b/lib/arm64/asm/assembler.h
> new file mode 100644
> index ..f801c0c43d02
> --- /dev/null
> +++ b/lib/arm64/asm/assembler.h
> @@ -0,0 +1,53 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Based on the file arch/arm64/include/asm/assembled.h from Linux v5.10, 
> which
> + * in turn is based on arch/arm/include/asm/assembler.h and
> + * arch/arm/mm/proc-macros.S
> + *
> + * Copyright (C) 1996-2000 Russell King
> + * Copyright (C) 2012 ARM Ltd.
> + */
> +#ifndef __ASSEMBLY__
> +#error "Only include this from assembly code"
> +#endif
> +
> +#ifndef __ASM_ASSEMBLER_H
> +#define __ASM_ASSEMBLER_H
> +
> +/*
> + * raw_dcache_line_size - get the minimum D-cache line size on this CPU
> + * from the CTR register.
> + */
> + .macro  raw_dcache_line_size, reg, tmp
> + mrs \tmp, ctr_el0   // read CTR
> + ubfm\tmp, \tmp, #16, #19// cache line size encoding

this encoding of ubfm is supposed to be written as:
ubfx \tmp, \tmp, #16, #4
This is also what objdump makes of the above.

The rest looks good, I convinced myself that the assembly algorithms are
correct.

Cheers,
Andre


> + mov \reg, #4// bytes per word
> + lsl \reg, \reg, \tmp// actual cache line size
> + .endm
> +
> +/*
> + * 

Re: [PATCH kvmtool v2 00/22] Unify I/O port and MMIO trap handling

2021-03-03 Thread Andre Przywara
On Tue, 2 Mar 2021 17:57:05 +
Alexandru Elisei  wrote:

Hi,

> I've started to review this iteration and I've come across this error when 
> trying
> to apply the patches:
> 
> $ git am --reject
> patches/unify-ioport-and-mmio/v2/Unify-I-O-port-and-MMIO-trap-handling.patch
> Applying: ioport: Remove ioport__setup_arch()
> Checking patch arm/ioport.c...
> Checking patch include/kvm/ioport.h...
> Checking patch ioport.c...
> Checking patch mips/kvm.c...
> Checking patch powerpc/ioport.c...
> Checking patch x86/ioport.c...
> Applied patch arm/ioport.c cleanly.
> Applied patch include/kvm/ioport.h cleanly.
> Applied patch ioport.c cleanly.
> Applied patch mips/kvm.c cleanly.
> Applied patch powerpc/ioport.c cleanly.
> Applied patch x86/ioport.c cleanly.
> Applying: hw/serial: Use device abstraction for FDT generator function
> Checking patch hw/serial.c...
> Checking patch include/kvm/kvm.h...
> Applied patch hw/serial.c cleanly.
> Applied patch include/kvm/kvm.h cleanly.
> Applying: ioport: Retire .generate_fdt_node functionality
> Checking patch include/kvm/ioport.h...
> Checking patch ioport.c...
> Applied patch include/kvm/ioport.h cleanly.
> Applied patch ioport.c cleanly.
> Applying: mmio: Extend handling to include ioport emulation
> Checking patch include/kvm/kvm.h...
> Checking patch ioport.c...
> Checking patch mmio.c...
> Applied patch include/kvm/kvm.h cleanly.
> Applied patch ioport.c cleanly.
> Applied patch mmio.c cleanly.
> Applying: hw/i8042: Clean up data types
> Checking patch hw/i8042.c...
> Applied patch hw/i8042.c cleanly.
> Applying: hw/i8042: Refactor trap handler
> Checking patch hw/i8042.c...
> Applied patch hw/i8042.c cleanly.
> Applying: hw/i8042: Switch to new trap handlers
> Checking patch hw/i8042.c...
> error: while searching for:
>         ioport__write8(data, value);
> }
> 
> /*
>  * Called when the OS has written to one of the keyboard's ports (0x60 or 
> 0x64)
>  */
> static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void
> *data, int size)
> {
>     kbd_io(vcpu, port, data, size, false, NULL);
> 
>     return true;
> }
> 
> static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
> void
> *data, int size)
> {
>     kbd_io(vcpu, port, data, size, true, NULL);
> 
>     return true;
> }
> 
> static struct ioport_operations kbd_ops = {
>     .io_in        = kbd_in,
>     .io_out        = kbd_out,
> };
> 
> int kbd__init(struct kvm *kvm)
> {
>     int r;
> 
>     kbd_reset();
>     state.kvm = kvm;
>     r = ioport__register(kvm, I8042_DATA_REG, _ops, 2, NULL);
>     if (r < 0)
>         return r;
>     r = ioport__register(kvm, I8042_COMMAND_REG, _ops, 2, NULL);
>     if (r < 0) {
>         ioport__unregister(kvm, I8042_DATA_REG);
>         return r;
>     }
> 
> 
> error: patch failed: hw/i8042.c:325
> Checking patch include/kvm/i8042.h...
> Applying patch hw/i8042.c with 1 reject...
> Rejected hunk #1.
> Applied patch include/kvm/i8042.h cleanly.
> Patch failed at 0007 hw/i8042: Switch to new trap handlers
> hint: Use 'git am --show-current-patch=diff' to see the failed patch
> When you have resolved this problem, run "git am --continue".
> If you prefer to skip this patch, run "git am --skip" instead.
> To restore the original branch and stop patching, run "git am --abort".
> 
> where the patch file is from patchwork.kernel.org [1], created when clicking 
> on
> the "series" button on the top right. I'm not sure what is causing the error,
> everything looks the same to me.

Ah, thanks for the heads up, and sorry for the pain! I can reproduce it,
and see what's going on: I made a last minute change, when creating the
changelog and going over the list of your comments again, and replaced
"false" with 0 in kbd_in() in patch 06/22, but only in the file, not in
the repo. So the follow-up patch - which removes this line again ;-) -
fails to apply.

> Regardless, I've applied the reject manually and everything looks ok.

Oh great, thanks! So I will wait with a resend until you are finished
with the review, and will then also upload to our gitlab.

Apologies for the inconvenience!

Cheers,
Andre


> 
> [1]
> https://patchwork.kernel.org/project/kvm/patch/20210225005915.26423-2-andre.przyw...@arm.com/
> 
> Thanks,
> 
> Alex
> 
> On 2/25/21 12:58 AM, Andre Przywara wrote:
> > Compared to v1 this has a few fixes, as suggested by Alex.
> > There is a new patch 20/22, which cleans up the ARM memory map
> > definition and adds some chart to make it more obvious what is going on.
> > For a changelog, see below.
> >

Re: [kvm-unit-tests PATCH 1/6] arm64: Remove unnecessary ISB when writing to SPSel

2021-03-03 Thread Andre Przywara
On Sat, 27 Feb 2021 10:41:56 +
Alexandru Elisei  wrote:

> Software can use the SPSel operand to write directly to PSTATE.SP.
> According to ARM DDI 0487F.b, page D1-2332, writes to PSTATE are
> self-synchronizing and no ISB is needed:
> 
> "Writes to the PSTATE fields have side-effects on various aspects of the PE
> operation. All of these side-effects are guaranteed:
> - Not to be visible to earlier instructions in the execution stream.
> - To be visible to later instructions in the execution stream."
> 
> Signed-off-by: Alexandru Elisei 

I am always a bit wary about *removing* barriers, but I can confirm
that the ARM ARM indeed makes this guarantee above, and SP access
sounds like an easy enough case, so:

Reviewed-by: Andre Przywara 

Cheers,
Andre

> ---
>  arm/cstart64.S | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/arm/cstart64.S b/arm/cstart64.S
> index 0428014aa58a..fc1930bcdb53 100644
> --- a/arm/cstart64.S
> +++ b/arm/cstart64.S
> @@ -54,7 +54,6 @@ start:
>   /* set up stack */
>   mov x4, #1
>   msr spsel, x4
> - isb
>   adrpx4, stackptr
>   add sp, x4, :lo12:stackptr
>  

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [kvm-unit-tests PATCH 6/6] arm64: Disable TTBR1_EL1 translation table walks

2021-03-03 Thread Andre Przywara
On Sat, 27 Feb 2021 10:42:01 +
Alexandru Elisei  wrote:

> From an architectural point of view, the PE can speculate instruction
> fetches and data reads at any time when the MMU is enabled using the
> translation tables from TTBR0_EL1 and TTBR1_EL1. kvm-unit-tests uses an
> identity map, and as such it only programs TTBR0_EL1 with a valid table and
> leaves TTBR1_EL1 unchanged. The reset value for TTBR1_EL1 is UNKNOWN, which
> means it is possible for the PE to perform reads from memory locations
> where accesses can cause side effects (like memory-mapped devices) as part
> of the speculated translation table walk.
> 
> So far, this hasn't been a problem, because KVM resets TTBR{0,1}_EL1 to
> zero, and that address is used for emulation for both qemu and kvmtool and
> it doesn't point to a real device. However, kvm-unit-tests shouldn't rely
> on a particular combination of hypervisor and userspace for correctness.
> Another situation where we can't rely on these assumptions being true is
> when kvm-unit-tests is run as an EFI app.
> 
> To prevent reads from arbitrary addresses, set the TCR_EL1.EPD1 bit to
> disable speculative translation table walks using TTBR1_EL1.
> 
> This is similar to EDK2 commit fafb7e9c110e ("ArmPkg: correct TTBR1_EL1
> settings in TCR_EL1"). Also mentioned in that commit is the Cortex-A57
> erratum 87 which impacts the hypervisor, but kvm-unit-tests is
> protected against it because asm_mmu_enable sets both the TCR_EL1.TG0 and
> TCR_EL1.TG1 bits when programming the register.
> 
> Suggested-by: Mark Rutland 
> Signed-off-by: Alexandru Elisei 

That sounds like a good idea. Verified the bit against the ARM ARM.

Reviewed-by: Andre Przywara 

Cheers,
Andre

> ---
>  lib/arm64/asm/pgtable-hwdef.h | 1 +
>  arm/cstart64.S| 3 ++-
>  2 files changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/arm64/asm/pgtable-hwdef.h b/lib/arm64/asm/pgtable-hwdef.h
> index 48a1d1ab1ac2..8c41fe123fb3 100644
> --- a/lib/arm64/asm/pgtable-hwdef.h
> +++ b/lib/arm64/asm/pgtable-hwdef.h
> @@ -136,6 +136,7 @@
>  #define TCR_ORGN_WBnWA   ((UL(3) << 10) | (UL(3) << 26))
>  #define TCR_ORGN_MASK((UL(3) << 10) | (UL(3) << 26))
>  #define TCR_SHARED   ((UL(3) << 12) | (UL(3) << 28))
> +#define TCR_EPD1 (UL(1) << 23)
>  #define TCR_TG0_4K   (UL(0) << 14)
>  #define TCR_TG0_64K  (UL(1) << 14)
>  #define TCR_TG0_16K  (UL(2) << 14)
> diff --git a/arm/cstart64.S b/arm/cstart64.S
> index 42a838ff4c38..3d359c8387c9 100644
> --- a/arm/cstart64.S
> +++ b/arm/cstart64.S
> @@ -181,7 +181,8 @@ asm_mmu_enable:
>   ldr x1, =TCR_TxSZ(VA_BITS) |\
>TCR_TG_FLAGS  |\
>TCR_IRGN_WBWA | TCR_ORGN_WBWA |\
> -  TCR_SHARED
> +  TCR_SHARED |   \
> +  TCR_EPD1
>   mrs x2, id_aa64mmfr0_el1
>   bfi x1, x2, #32, #3
>   msr tcr_el1, x1

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [kvm-unit-tests PATCH 5/6] arm64: Configure SCTLR_EL1 at boot

2021-03-03 Thread Andre Przywara
On Sat, 27 Feb 2021 10:42:00 +
Alexandru Elisei  wrote:

Hi,

> Some fields in SCTLR_EL1 are UNKNOWN at reset and the arm64 boot
> requirements, as stated by Linux in Documentation/arm64/booting.rst, do not
> specify a particular value for all the fields. Do not rely on the good will
> of the hypervisor and userspace to set SCTLR_EL1 to a sane value (by their
> definition of sane) and set SCTLR_EL1 explicitely before running setup().
> This will ensure that all tests are performed with the hardware set up
> identically, regardless of the KVM or VMM versions.
> 
> Signed-off-by: Alexandru Elisei 

Can confirm that the RES1 bits match the ARM ARM, and that it's indeed
a good idea to start from a known good state:

Reviewed-by: Andre Przywara 

Cheers,
Andre

> ---
>  lib/arm64/asm/sysreg.h | 7 +++
>  arm/cstart64.S | 5 +
>  2 files changed, 12 insertions(+)
> 
> diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h
> index 9d6b4fc66936..18c4ed39557a 100644
> --- a/lib/arm64/asm/sysreg.h
> +++ b/lib/arm64/asm/sysreg.h
> @@ -8,6 +8,8 @@
>  #ifndef _ASMARM64_SYSREG_H_
>  #define _ASMARM64_SYSREG_H_
>  
> +#include 
> +
>  #define sys_reg(op0, op1, crn, crm, op2) \
>   op0)&3)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5))
>  
> @@ -87,4 +89,9 @@ asm(
>  #define SCTLR_EL1_A  (1 << 1)
>  #define SCTLR_EL1_M  (1 << 0)
>  
> +#define SCTLR_EL1_RES1   (_BITUL(7) | _BITUL(8) | _BITUL(11) | 
> _BITUL(20) | \
> +  _BITUL(22) | _BITUL(23) | _BITUL(28) | _BITUL(29))
> +#define INIT_SCTLR_EL1_MMU_OFF   \
> + SCTLR_EL1_RES1
> +
>  #endif /* _ASMARM64_SYSREG_H_ */
> diff --git a/arm/cstart64.S b/arm/cstart64.S
> index f6c5d2ebccf3..42a838ff4c38 100644
> --- a/arm/cstart64.S
> +++ b/arm/cstart64.S
> @@ -52,6 +52,11 @@ start:
>   b   1b
>  
>  1:
> + /* set SCTLR_EL1 to a known value */
> + ldr x4, =INIT_SCTLR_EL1_MMU_OFF
> + msr sctlr_el1, x4
> + isb
> +
>   /* set up stack */
>   mov x4, #1
>   msr spsel, x4

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [kvm-unit-tests PATCH 4/6] lib: arm64: Consolidate register definitions to sysreg.h

2021-03-03 Thread Andre Przywara
On Sat, 27 Feb 2021 10:41:59 +
Alexandru Elisei  wrote:

> Move system register field definitions to sysreg.h, where the opcodes for
> system register access are defined, to align ourselves with the Linux
> kernel. EL2 support, needed for EFI and nested virtualization testing, will
> require additional register and field definions, and having them in the
> same place as Linux will make maintenance easier.
> 
> Signed-off-by: Alexandru Elisei 

Checked to be just moves, and it compiles, so:

Reviewed-by: Andre Przywara 

Cheers,
Andre

> ---
>  lib/arm64/asm/arch_gicv3.h |  6 --
>  lib/arm64/asm/processor.h  | 10 --
>  lib/arm64/asm/sysreg.h | 17 +
>  arm/cstart64.S |  2 +-
>  4 files changed, 18 insertions(+), 17 deletions(-)
> 
> diff --git a/lib/arm64/asm/arch_gicv3.h b/lib/arm64/asm/arch_gicv3.h
> index a7994ec2fbbe..fdee4de1f1f6 100644
> --- a/lib/arm64/asm/arch_gicv3.h
> +++ b/lib/arm64/asm/arch_gicv3.h
> @@ -10,12 +10,6 @@
>  
>  #include 
>  
> -#define ICC_PMR_EL1  sys_reg(3, 0, 4, 6, 0)
> -#define ICC_SGI1R_EL1sys_reg(3, 0, 12, 11, 5)
> -#define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
> -#define ICC_EOIR1_EL1sys_reg(3, 0, 12, 12, 1)
> -#define ICC_GRPEN1_EL1   sys_reg(3, 0, 12, 12, 7)
> -
>  #ifndef __ASSEMBLY__
>  
>  #include 
> diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
> index cdc2463e1981..4a3d826ab560 100644
> --- a/lib/arm64/asm/processor.h
> +++ b/lib/arm64/asm/processor.h
> @@ -6,16 +6,6 @@
>   * This work is licensed under the terms of the GNU LGPL, version 2.
>   */
>  
> -/* System Control Register (SCTLR_EL1) bits */
> -#define SCTLR_EL1_EE (1 << 25)
> -#define SCTLR_EL1_WXN(1 << 19)
> -#define SCTLR_EL1_I  (1 << 12)
> -#define SCTLR_EL1_SA0(1 << 4)
> -#define SCTLR_EL1_SA (1 << 3)
> -#define SCTLR_EL1_C  (1 << 2)
> -#define SCTLR_EL1_A  (1 << 1)
> -#define SCTLR_EL1_M  (1 << 0)
> -
>  #ifndef __ASSEMBLY__
>  #include 
>  #include 
> diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h
> index 378bf7ebb3b5..9d6b4fc66936 100644
> --- a/lib/arm64/asm/sysreg.h
> +++ b/lib/arm64/asm/sysreg.h
> @@ -70,4 +70,21 @@ asm(
>  ".endm\n"
>  );
>  #endif /* __ASSEMBLY__ */
> +
> +#define ICC_PMR_EL1  sys_reg(3, 0, 4, 6, 0)
> +#define ICC_SGI1R_EL1sys_reg(3, 0, 12, 11, 5)
> +#define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
> +#define ICC_EOIR1_EL1sys_reg(3, 0, 12, 12, 1)
> +#define ICC_GRPEN1_EL1   sys_reg(3, 0, 12, 12, 7)
> +
> +/* System Control Register (SCTLR_EL1) bits */
> +#define SCTLR_EL1_EE (1 << 25)
> +#define SCTLR_EL1_WXN(1 << 19)
> +#define SCTLR_EL1_I  (1 << 12)
> +#define SCTLR_EL1_SA0(1 << 4)
> +#define SCTLR_EL1_SA (1 << 3)
> +#define SCTLR_EL1_C  (1 << 2)
> +#define SCTLR_EL1_A  (1 << 1)
> +#define SCTLR_EL1_M  (1 << 0)
> +
>  #endif /* _ASMARM64_SYSREG_H_ */
> diff --git a/arm/cstart64.S b/arm/cstart64.S
> index c1deff842f03..f6c5d2ebccf3 100644
> --- a/arm/cstart64.S
> +++ b/arm/cstart64.S
> @@ -10,9 +10,9 @@
>  #include 
>  #include 
>  #include 
> -#include 
>  #include 
>  #include 
> +#include 
>  
>  .section .init
>  

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [kvm-unit-tests PATCH] configure: arm/arm64: Add --earlycon option to set UART type and address

2021-03-03 Thread Andre Przywara
On Fri, 19 Feb 2021 16:37:18 +
Alexandru Elisei  wrote:

> Currently, the UART early address is set indirectly with the --vmm option
> and there are only two possible values: if the VMM is qemu (the default),
> then the UART address is set to 0x0900; if the VMM is kvmtool, then the
> UART address is set to 0x3f8.
> 
> There several efforts under way to change the kvmtool UART address, and
> kvm-unit-tests so far hasn't had mechanism to let the user set a specific
> address, which means that the early UART won't be available.
> 
> This situation will only become worse as kvm-unit-tests gains support to
> run as an EFI app, as each platform will have their own UART type and
> address.
> 
> To address both issues, a new configure option is added, --earlycon. The
> syntax and semantics are identical to the kernel parameter with the same
> name.

Nice one! I like that reusing of an existing scheme.

> Specifying this option will overwrite the UART address set by --vmm.
> 
> At the moment, the UART type and register width parameters are ignored
> since both qemu's and kvmtool's UART emulation use the same offset for the
> TX register and no other registers are used by kvm-unit-tests, but the
> parameters will become relevant once EFI support is added.
> 
> Signed-off-by: Alexandru Elisei 
> ---
> The kvmtool patches I was referring to are the patches to unify ioport and
> MMIO emulation [1] and to allow the user to specify a custom memory layout
> for the VM [2] (these patches are very old, but I plan to revive them after
> the ioport and MMIO unification series are merged).
> 
> [1] 
> https://lore.kernel.org/kvm/20201210142908.169597-1-andre.przyw...@arm.com/T/#t
> [2] 
> https://lore.kernel.org/kvm/1569245722-23375-1-git-send-email-alexandru.eli...@arm.com/
> 
>  configure | 35 +++
>  1 file changed, 35 insertions(+)
> 
> diff --git a/configure b/configure
> index cdcd34e94030..d94b92255088 100755
> --- a/configure
> +++ b/configure
> @@ -26,6 +26,7 @@ errata_force=0
>  erratatxt="$srcdir/errata.txt"
>  host_key_document=
>  page_size=
> +earlycon=
>  
>  usage() {
>  cat <<-EOF
> @@ -54,6 +55,17 @@ usage() {
>   --page-size=PAGE_SIZE
>  Specify the page size (translation granule) 
> (4k, 16k or
>  64k, default is 64k, arm64 only)
> + --earlycon=EARLYCON
> +Specify the UART name, type and address 
> (optional, arm and
> +arm64 only). The specified address will 
> overwrite the UART
> +address set by the --vmm option. EARLYCON 
> can be on of (case
> +sensitive):
> +uart[8250],mmio,ADDR
> +Specify an 8250 compatible UART at address 
> ADDR. Supported
> +register stride is 8 bit only.
> +pl011,mmio,ADDR
> +Specify a PL011 compatible UART at address 
> ADDR. Supported
> +register stride is 8 bit only.

I think the PL011 only ever specified 32-bit register accesses? I just
see that we actually do a writeb() for puts, that is not guaranteed to
work on a hardware PL011, AFAIK. I guess QEMU just doesn't care ...
Looks like we should fix this, maybe we get mmio32 for uart8250 for
free, then.

The kernel specifies "pl011,mmio32,ADDR" or "pl011,ADDR", so I think we
should keep it compatible. "mmio[32]" is pretty much redundant on the
PL011 (no port I/O), I think it's just for consistency with the 8250.
Can you tweak the routine below to make this optional, and also accept
mmio32?

Cheers,
Andre

>  EOF
>  exit 1
>  }
> @@ -112,6 +124,9 @@ while [[ "$1" = -* ]]; do
>   --page-size)
>   page_size="$arg"
>   ;;
> + --earlycon)
> + earlycon="$arg"
> + ;;
>   --help)
>   usage
>   ;;
> @@ -170,6 +185,26 @@ elif [ "$arch" = "arm" ] || [ "$arch" = "arm64" ]; then
>  echo '--vmm must be one of "qemu" or "kvmtool"!'
>  usage
>  fi
> +
> +if [ "$earlycon" ]; then
> +name=$(echo $earlycon|cut -d',' -f1)
> +if [ "$name" != "uart" ] && [ "$name" != "uart8250" ] &&
> +[ "$name" != "pl011" ]; then
> +echo "unknown earlycon name: $name"
> +usage
> +fi
> +type=$(echo $earlycon|cut -d',' -f2)
> +if [ "$type" != "mmio" ]; then
> +echo "unknown earlycon type: $type"
> +usage
> +fi
> +addr=$(echo $earlycon|cut -d',' -f3)
> +if [ -z "$addr" ]; then
> +echo "missing earlycon address"
> +usage
> +fi
> +arm_uart_early_addr=$addr
> +fi
>  elif [ "$arch" = "ppc64" ]; then
>  testdir=powerpc
>  firmware="$testdir/boot_rom.bin"


[PATCH kvmtool v2 22/22] hw/rtc: ARM/arm64: Use MMIO at higher addresses

2021-02-24 Thread Andre Przywara
Using the RTC device at its legacy I/O address as set by IBM in 1981
was a kludge we used for simplicity on ARM platforms as well.
However this imposes problems due to their missing alignment and overlap
with the PCI I/O address space.

Now that we can switch a device easily between using ioports and
MMIO, let's move the RTC out of the first 4K of memory on ARM platforms.

That should be transparent for well behaved guests, since the change is
naturally reflected in the device tree.

Signed-off-by: Andre Przywara 
---
 arm/include/arm-common/kvm-arch.h |  3 +++
 hw/rtc.c  | 24 
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/arm/include/arm-common/kvm-arch.h 
b/arm/include/arm-common/kvm-arch.h
index 633ea8fa..02100c48 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -31,6 +31,9 @@
 #define ARM_UART_MMIO_BASE ARM_MMIO_AREA
 #define ARM_UART_MMIO_SIZE 0x1
 
+#define ARM_RTC_MMIO_BASE  (ARM_UART_MMIO_BASE + ARM_UART_MMIO_SIZE)
+#define ARM_RTC_MMIO_SIZE  0x1
+
 #define KVM_FLASH_MMIO_BASE(ARM_MMIO_AREA + 0x100)
 #define KVM_FLASH_MAX_SIZE 0x100
 
diff --git a/hw/rtc.c b/hw/rtc.c
index ee4c9102..aec31c52 100644
--- a/hw/rtc.c
+++ b/hw/rtc.c
@@ -5,6 +5,15 @@
 
 #include 
 
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#define RTC_BUS_TYPE   DEVICE_BUS_MMIO
+#define RTC_BASE_ADDRESS   ARM_RTC_MMIO_BASE
+#else
+/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
+#define RTC_BUS_TYPE   DEVICE_BUS_IOPORT
+#define RTC_BASE_ADDRESS   0x70
+#endif
+
 /*
  * MC146818 RTC registers
  */
@@ -49,7 +58,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 
*data,
time_t ti;
 
if (is_write) {
-   if (addr == 0x70) { /* index register */
+   if (addr == RTC_BASE_ADDRESS) { /* index register */
u8 value = ioport__read8(data);
 
vcpu->kvm->nmi_disabled = value & (1UL << 7);
@@ -70,7 +79,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 
*data,
return;
}
 
-   if (addr == 0x70)
+   if (addr == RTC_BASE_ADDRESS)   /* index register is write-only */
return;
 
time();
@@ -127,7 +136,7 @@ static void generate_rtc_fdt_node(void *fdt,
u8 irq,
enum irq_type))
 {
-   u64 reg_prop[2] = { cpu_to_fdt64(0x70), cpu_to_fdt64(2) };
+   u64 reg_prop[2] = { cpu_to_fdt64(RTC_BASE_ADDRESS), cpu_to_fdt64(2) };
 
_FDT(fdt_begin_node(fdt, "rtc"));
_FDT(fdt_property_string(fdt, "compatible", "motorola,mc146818"));
@@ -139,7 +148,7 @@ static void generate_rtc_fdt_node(void *fdt,
 #endif
 
 struct device_header rtc_dev_hdr = {
-   .bus_type = DEVICE_BUS_IOPORT,
+   .bus_type = RTC_BUS_TYPE,
.data = generate_rtc_fdt_node,
 };
 
@@ -151,8 +160,8 @@ int rtc__init(struct kvm *kvm)
if (r < 0)
return r;
 
-   /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-   r = kvm__register_pio(kvm, 0x0070, 2, cmos_ram_io, NULL);
+   r = kvm__register_iotrap(kvm, RTC_BASE_ADDRESS, 2, cmos_ram_io, NULL,
+RTC_BUS_TYPE);
if (r < 0)
goto out_device;
 
@@ -170,8 +179,7 @@ dev_init(rtc__init);
 
 int rtc__exit(struct kvm *kvm)
 {
-   /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-   kvm__deregister_pio(kvm, 0x0070);
+   kvm__deregister_iotrap(kvm, RTC_BASE_ADDRESS, RTC_BUS_TYPE);
 
return 0;
 }
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 21/22] hw/serial: ARM/arm64: Use MMIO at higher addresses

2021-02-24 Thread Andre Przywara
Using the UART devices at their legacy I/O addresses as set by IBM in
1981 was a kludge we used for simplicity on ARM platforms as well.
However this imposes problems due to their missing alignment and overlap
with the PCI I/O address space.

Now that we can switch a device easily between using ioports and MMIO,
let's move the UARTs out of the first 4K of memory on ARM platforms.

That should be transparent for well behaved guests, since the change is
naturally reflected in the device tree. Even "earlycon" keeps working,
as the stdout-path property is adjusted automatically.

People providing direct earlycon parameters via the command line need to
adjust it to: "earlycon=uart,mmio,0x100".

Signed-off-by: Andre Przywara 
---
 arm/include/arm-common/kvm-arch.h |  3 +++
 hw/serial.c   | 45 ---
 2 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/arm/include/arm-common/kvm-arch.h 
b/arm/include/arm-common/kvm-arch.h
index b12255b0..633ea8fa 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -28,6 +28,9 @@
 #define ARM_IOPORT_SIZE(1U << 16)
 
 
+#define ARM_UART_MMIO_BASE ARM_MMIO_AREA
+#define ARM_UART_MMIO_SIZE 0x1
+
 #define KVM_FLASH_MMIO_BASE(ARM_MMIO_AREA + 0x100)
 #define KVM_FLASH_MAX_SIZE 0x100
 
diff --git a/hw/serial.c b/hw/serial.c
index 4be188a1..1854add2 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -13,6 +13,17 @@
 
 #include 
 
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#define serial_iobase(nr)  (ARM_UART_MMIO_BASE + (nr) * 0x1000)
+#define serial_irq(nr) (32 + (nr))
+#define SERIAL8250_BUS_TYPEDEVICE_BUS_MMIO
+#else
+#define serial_iobase(nr)  nr) & 1) ? 0x200 : 0x300) + \
+((nr) >= 2 ? 0xe8 : 0xf8))
+#define serial_irq(nr) (((nr) & 1) ? 3 : 4)
+#define SERIAL8250_BUS_TYPEDEVICE_BUS_IOPORT
+#endif
+
 /*
  * This fakes a U6_16550A. The fifo len needs to be 64 as the kernel
  * expects that for autodetection.
@@ -27,7 +38,7 @@ struct serial8250_device {
struct mutexmutex;
u8  id;
 
-   u16 iobase;
+   u32 iobase;
u8  irq;
u8  irq_state;
int txcnt;
@@ -65,56 +76,56 @@ static struct serial8250_device devices[] = {
/* ttyS0 */
[0] = {
.dev_hdr = {
-   .bus_type   = DEVICE_BUS_IOPORT,
+   .bus_type   = SERIAL8250_BUS_TYPE,
.data   = serial8250_generate_fdt_node,
},
.mutex  = MUTEX_INITIALIZER,
 
.id = 0,
-   .iobase = 0x3f8,
-   .irq= 4,
+   .iobase = serial_iobase(0),
+   .irq= serial_irq(0),
 
SERIAL_REGS_SETTING
},
/* ttyS1 */
[1] = {
.dev_hdr = {
-   .bus_type   = DEVICE_BUS_IOPORT,
+   .bus_type   = SERIAL8250_BUS_TYPE,
.data   = serial8250_generate_fdt_node,
},
.mutex  = MUTEX_INITIALIZER,
 
.id = 1,
-   .iobase = 0x2f8,
-   .irq= 3,
+   .iobase = serial_iobase(1),
+   .irq= serial_irq(1),
 
SERIAL_REGS_SETTING
},
/* ttyS2 */
[2] = {
.dev_hdr = {
-   .bus_type   = DEVICE_BUS_IOPORT,
+   .bus_type   = SERIAL8250_BUS_TYPE,
.data   = serial8250_generate_fdt_node,
},
.mutex  = MUTEX_INITIALIZER,
 
.id = 2,
-   .iobase = 0x3e8,
-   .irq= 4,
+   .iobase = serial_iobase(2),
+   .irq= serial_irq(2),
 
SERIAL_REGS_SETTING
},
/* ttyS3 */
[3] = {
.dev_hdr = {
-   .bus_type   = DEVICE_BUS_IOPORT,
+   .bus_type   = SERIAL8250_BUS_TYPE,
.data   = serial8250_generate_fdt_node,
},
.mutex  = MUTEX_INITIALIZER,
 
.id = 3,
-   .iobase = 0x2e8,
-   .irq= 3,
+   .iobase = s

[PATCH kvmtool v2 20/22] arm: Reorganise and document memory map

2021-02-24 Thread Andre Przywara
The hardcoded memory map we expose to a guest is currently described
using a series of partially interconnected preprocessor constants,
which is hard to read and follow.

In preparation for moving the UART and RTC to some different MMIO
region, document the current map with some ASCII art, and clean up the
definition of the sections.

No functional change.

Signed-off-by: Andre Przywara 
---
 arm/include/arm-common/kvm-arch.h | 41 ++-
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/arm/include/arm-common/kvm-arch.h 
b/arm/include/arm-common/kvm-arch.h
index d84e50cd..b12255b0 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/arm-common/kvm-arch.h
@@ -7,14 +7,33 @@
 
 #include "arm-common/gic.h"
 
+/*
+ * The memory map used for ARM guests (not to scale):
+ *
+ * 0  64K  16M 32M 48M1GB   2GB
+ * +---+-..-+---+---+----+-+--.--+---..
+ * | (PCI) || int.  |   || | |
+ * |  I/O  || MMIO: | Flash | virtio | GIC |   PCI   |  DRAM
+ * | ports || UART, |   |  MMIO  | |  (AXI)  |
+ * |   || RTC   |   || | |
+ * +---+-..-+---+---+----+-+--.--+---..
+ */
+
 #define ARM_IOPORT_AREA_AC(0x, UL)
-#define ARM_FLASH_AREA _AC(0x0200, UL)
-#define ARM_MMIO_AREA  _AC(0x0300, UL)
+#define ARM_MMIO_AREA  _AC(0x0100, UL)
 #define ARM_AXI_AREA   _AC(0x4000, UL)
 #define ARM_MEMORY_AREA_AC(0x8000, UL)
 
-#define ARM_LOMAP_MAX_MEMORY   ((1ULL << 32) - ARM_MEMORY_AREA)
-#define ARM_HIMAP_MAX_MEMORY   ((1ULL << 40) - ARM_MEMORY_AREA)
+#define KVM_IOPORT_AREAARM_IOPORT_AREA
+#define ARM_IOPORT_SIZE(1U << 16)
+
+
+#define KVM_FLASH_MMIO_BASE(ARM_MMIO_AREA + 0x100)
+#define KVM_FLASH_MAX_SIZE 0x100
+
+#define KVM_VIRTIO_MMIO_AREA   (KVM_FLASH_MMIO_BASE + KVM_FLASH_MAX_SIZE)
+#define ARM_VIRTIO_MMIO_SIZE   (ARM_AXI_AREA - \
+   (KVM_VIRTIO_MMIO_AREA + ARM_GIC_SIZE))
 
 #define ARM_GIC_DIST_BASE  (ARM_AXI_AREA - ARM_GIC_DIST_SIZE)
 #define ARM_GIC_CPUI_BASE  (ARM_GIC_DIST_BASE - ARM_GIC_CPUI_SIZE)
@@ -22,19 +41,17 @@
 #define ARM_GIC_DIST_SIZE  0x1
 #define ARM_GIC_CPUI_SIZE  0x2
 
-#define KVM_FLASH_MMIO_BASEARM_FLASH_AREA
-#define KVM_FLASH_MAX_SIZE (ARM_MMIO_AREA - ARM_FLASH_AREA)
 
-#define ARM_IOPORT_SIZE(1U << 16)
-#define ARM_VIRTIO_MMIO_SIZE   (ARM_AXI_AREA - (ARM_MMIO_AREA + ARM_GIC_SIZE))
+#define KVM_PCI_CFG_AREA   ARM_AXI_AREA
 #define ARM_PCI_CFG_SIZE   (1ULL << 24)
+#define KVM_PCI_MMIO_AREA  (KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
 #define ARM_PCI_MMIO_SIZE  (ARM_MEMORY_AREA - \
(ARM_AXI_AREA + ARM_PCI_CFG_SIZE))
 
-#define KVM_IOPORT_AREAARM_IOPORT_AREA
-#define KVM_PCI_CFG_AREA   ARM_AXI_AREA
-#define KVM_PCI_MMIO_AREA  (KVM_PCI_CFG_AREA + ARM_PCI_CFG_SIZE)
-#define KVM_VIRTIO_MMIO_AREA   ARM_MMIO_AREA
+
+#define ARM_LOMAP_MAX_MEMORY   ((1ULL << 32) - ARM_MEMORY_AREA)
+#define ARM_HIMAP_MAX_MEMORY   ((1ULL << 40) - ARM_MEMORY_AREA)
+
 
 #define KVM_IOEVENTFD_HAS_PIO  0
 
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 19/22] Remove ioport specific routines

2021-02-24 Thread Andre Przywara
Now that all users of the dedicated ioport trap handler interface are
gone, we can retire the code associated with it.

This removes ioport.c and ioport.h, along with removing prototypes from
other header files.

This also transfers the responsibility for port I/O trap handling
entirely into the new routine in mmio.c.

Signed-off-by: Andre Przywara 
---
 Makefile |   1 -
 include/kvm/ioport.h |  27 --
 include/kvm/kvm.h|   2 -
 ioport.c | 195 ---
 mmio.c   |   2 +-
 5 files changed, 1 insertion(+), 226 deletions(-)
 delete mode 100644 ioport.c

diff --git a/Makefile b/Makefile
index 35bb1182..94ff5da6 100644
--- a/Makefile
+++ b/Makefile
@@ -56,7 +56,6 @@ OBJS  += framebuffer.o
 OBJS   += guest_compat.o
 OBJS   += hw/rtc.o
 OBJS   += hw/serial.o
-OBJS   += ioport.o
 OBJS   += irq.o
 OBJS   += kvm-cpu.o
 OBJS   += kvm.o
diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
index a61038e2..b6f579cb 100644
--- a/include/kvm/ioport.h
+++ b/include/kvm/ioport.h
@@ -1,13 +1,8 @@
 #ifndef KVM__IOPORT_H
 #define KVM__IOPORT_H
 
-#include "kvm/devices.h"
 #include "kvm/kvm-cpu.h"
-#include "kvm/rbtree-interval.h"
-#include "kvm/fdt.h"
 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -15,30 +10,8 @@
 /* some ports we reserve for own use */
 #define IOPORT_DBG 0xe0
 
-struct kvm;
-
-struct ioport {
-   struct rb_int_node  node;
-   struct ioport_operations*ops;
-   void*priv;
-   struct device_headerdev_hdr;
-   u32 refcount;
-   boolremove;
-};
-
-struct ioport_operations {
-   bool (*io_in)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size);
-   bool (*io_out)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size);
-};
-
 void ioport__map_irq(u8 *irq);
 
-int __must_check ioport__register(struct kvm *kvm, u16 port, struct 
ioport_operations *ops,
- int count, void *param);
-int ioport__unregister(struct kvm *kvm, u16 port);
-int ioport__init(struct kvm *kvm);
-int ioport__exit(struct kvm *kvm);
-
 static inline u8 ioport__read8(u8 *data)
 {
return *data;
diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
index 306b258a..6c28afa3 100644
--- a/include/kvm/kvm.h
+++ b/include/kvm/kvm.h
@@ -126,8 +126,6 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
 void kvm__irq_trigger(struct kvm *kvm, int irq);
 bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int 
direction, int size, u32 count);
 bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, 
u8 is_write);
-bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
- int direction, int size, u32 count);
 int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void 
*userspace_addr);
 int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void 
*userspace_addr,
  enum kvm_mem_type type);
diff --git a/ioport.c b/ioport.c
deleted file mode 100644
index ce29e7e7..
--- a/ioport.c
+++ /dev/null
@@ -1,195 +0,0 @@
-#include "kvm/ioport.h"
-
-#include "kvm/kvm.h"
-#include "kvm/util.h"
-#include "kvm/rbtree-interval.h"
-#include "kvm/mutex.h"
-
-#include  /* for KVM_EXIT_* */
-#include 
-
-#include 
-#include 
-#include 
-#include 
-
-#define ioport_node(n) rb_entry(n, struct ioport, node)
-
-static DEFINE_MUTEX(ioport_lock);
-
-static struct rb_root  ioport_tree = RB_ROOT;
-
-static struct ioport *ioport_search(struct rb_root *root, u64 addr)
-{
-   struct rb_int_node *node;
-
-   node = rb_int_search_single(root, addr);
-   if (node == NULL)
-   return NULL;
-
-   return ioport_node(node);
-}
-
-static int ioport_insert(struct rb_root *root, struct ioport *data)
-{
-   return rb_int_insert(root, >node);
-}
-
-static void ioport_remove(struct rb_root *root, struct ioport *data)
-{
-   rb_int_erase(root, >node);
-}
-
-static struct ioport *ioport_get(struct rb_root *root, u64 addr)
-{
-   struct ioport *ioport;
-
-   mutex_lock(_lock);
-   ioport = ioport_search(root, addr);
-   if (ioport)
-   ioport->refcount++;
-   mutex_unlock(_lock);
-
-   return ioport;
-}
-
-/* Called with ioport_lock held. */
-static void ioport_unregister(struct rb_root *root, struct ioport *data)
-{
-   ioport_remove(root, data);
-   free(data);
-}
-
-static void ioport_put(struct rb_root *root, struct ioport *data)
-{
-   mutex_lock(_lock);
-   data->refcount--;
-   if (data->remove && data->refcount == 0)
-   ioport_unregister(root, data);
-   mutex_unlock(_lock);
-}
-
-int ioport__registe

[PATCH kvmtool v2 18/22] pci: Switch trap handling to use MMIO handler

2021-02-24 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Merge the existing _in and _out handlers to adhere to that MMIO
interface, and register these using the new registration function.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 pci.c | 82 +--
 1 file changed, 24 insertions(+), 58 deletions(-)

diff --git a/pci.c b/pci.c
index 2e2c0270..d6da79e0 100644
--- a/pci.c
+++ b/pci.c
@@ -87,29 +87,16 @@ static void *pci_config_address_ptr(u16 port)
return base + offset;
 }
 
-static bool pci_config_address_out(struct ioport *ioport, struct kvm_cpu 
*vcpu, u16 port, void *data, int size)
+static void pci_config_address_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+   u32 len, u8 is_write, void *ptr)
 {
-   void *p = pci_config_address_ptr(port);
+   void *p = pci_config_address_ptr(addr);
 
-   memcpy(p, data, size);
-
-   return true;
-}
-
-static bool pci_config_address_in(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
-{
-   void *p = pci_config_address_ptr(port);
-
-   memcpy(data, p, size);
-
-   return true;
+   if (is_write)
+   memcpy(p, data, len);
+   else
+   memcpy(data, p, len);
 }
-
-static struct ioport_operations pci_config_address_ops = {
-   .io_in  = pci_config_address_in,
-   .io_out = pci_config_address_out,
-};
-
 static bool pci_device_exists(u8 bus_number, u8 device_number, u8 
function_number)
 {
union pci_config_address pci_config_address;
@@ -125,49 +112,27 @@ static bool pci_device_exists(u8 bus_number, u8 
device_number, u8 function_numbe
return !IS_ERR_OR_NULL(device__find_dev(DEVICE_BUS_PCI, device_number));
 }
 
-static bool pci_config_data_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
-{
-   union pci_config_address pci_config_address;
-
-   if (size > 4)
-   size = 4;
-
-   pci_config_address.w = ioport__read32(_config_address_bits);
-   /*
-* If someone accesses PCI configuration space offsets that are not
-* aligned to 4 bytes, it uses ioports to signify that.
-*/
-   pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
-
-   pci__config_wr(vcpu->kvm, pci_config_address, data, size);
-
-   return true;
-}
-
-static bool pci_config_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
+static void pci_config_data_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+u32 len, u8 is_write, void *kvm)
 {
union pci_config_address pci_config_address;
 
-   if (size > 4)
-   size = 4;
+   if (len > 4)
+   len = 4;
 
pci_config_address.w = ioport__read32(_config_address_bits);
/*
 * If someone accesses PCI configuration space offsets that are not
 * aligned to 4 bytes, it uses ioports to signify that.
 */
-   pci_config_address.reg_offset = port - PCI_CONFIG_DATA;
+   pci_config_address.reg_offset = addr - PCI_CONFIG_DATA;
 
-   pci__config_rd(vcpu->kvm, pci_config_address, data, size);
-
-   return true;
+   if (is_write)
+   pci__config_wr(vcpu->kvm, pci_config_address, data, len);
+   else
+   pci__config_rd(vcpu->kvm, pci_config_address, data, len);
 }
 
-static struct ioport_operations pci_config_data_ops = {
-   .io_in  = pci_config_data_in,
-   .io_out = pci_config_data_out,
-};
-
 static int pci_activate_bar(struct kvm *kvm, struct pci_device_header *pci_hdr,
int bar_num)
 {
@@ -512,11 +477,12 @@ int pci__init(struct kvm *kvm)
 {
int r;
 
-   r = ioport__register(kvm, PCI_CONFIG_DATA + 0, _config_data_ops, 4, 
NULL);
+   r = kvm__register_pio(kvm, PCI_CONFIG_DATA, 4,
+pci_config_data_mmio, NULL);
if (r < 0)
return r;
-
-   r = ioport__register(kvm, PCI_CONFIG_ADDRESS + 0, 
_config_address_ops, 4, NULL);
+   r = kvm__register_pio(kvm, PCI_CONFIG_ADDRESS, 4,
+pci_config_address_mmio, NULL);
if (r < 0)
goto err_unregister_data;
 
@@ -528,17 +494,17 @@ int pci__init(struct kvm *kvm)
return 0;
 
 err_unregister_addr:
-   ioport__unregister(kvm, PCI_CONFIG_ADDRESS);
+   kvm__deregister_pio(kvm, PCI_CONFIG_ADDRESS);
 err_unregister_data:
-   ioport__unregister(kvm, PCI_CONFIG_DATA);
+   kvm__deregister_pio(kvm, PCI_CONFIG_DATA);
return r;
 }
 dev_base_init(pci__init);
 
 int pci__exit(struct kvm *kvm)
 {
-   ioport__unregister(kvm, PCI_CONFIG_DATA);
-   ioport__unregister(kvm, PCI_CONFIG_ADDRESS);
+   kvm__deregist

[PATCH kvmtool v2 17/22] virtio: Switch trap handling to use MMIO handler

2021-02-24 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Adjust the existing MMIO callback routine to automatically determine
the region this trap came through, and call the existing I/O handlers.
Register the ioport region using the new registration function.

Signed-off-by: Andre Przywara 
---
 virtio/pci.c | 46 ++
 1 file changed, 14 insertions(+), 32 deletions(-)

diff --git a/virtio/pci.c b/virtio/pci.c
index 6eea6c68..eb91f512 100644
--- a/virtio/pci.c
+++ b/virtio/pci.c
@@ -178,15 +178,6 @@ static bool virtio_pci__data_in(struct kvm_cpu *vcpu, 
struct virtio_device *vdev
return ret;
 }
 
-static bool virtio_pci__io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
-{
-   struct virtio_device *vdev = ioport->priv;
-   struct virtio_pci *vpci = vdev->virtio;
-   unsigned long offset = port - virtio_pci__port_addr(vpci);
-
-   return virtio_pci__data_in(vcpu, vdev, offset, data, size);
-}
-
 static void update_msix_map(struct virtio_pci *vpci,
struct msix_table *msix_entry, u32 vecnum)
 {
@@ -334,20 +325,6 @@ static bool virtio_pci__data_out(struct kvm_cpu *vcpu, 
struct virtio_device *vde
return ret;
 }
 
-static bool virtio_pci__io_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
-{
-   struct virtio_device *vdev = ioport->priv;
-   struct virtio_pci *vpci = vdev->virtio;
-   unsigned long offset = port - virtio_pci__port_addr(vpci);
-
-   return virtio_pci__data_out(vcpu, vdev, offset, data, size);
-}
-
-static struct ioport_operations virtio_pci__io_ops = {
-   .io_in  = virtio_pci__io_in,
-   .io_out = virtio_pci__io_out,
-};
-
 static void virtio_pci__msix_mmio_callback(struct kvm_cpu *vcpu,
   u64 addr, u8 *data, u32 len,
   u8 is_write, void *ptr)
@@ -455,12 +432,19 @@ static void virtio_pci__io_mmio_callback(struct kvm_cpu 
*vcpu,
 {
struct virtio_device *vdev = ptr;
struct virtio_pci *vpci = vdev->virtio;
-   u32 mmio_addr = virtio_pci__mmio_addr(vpci);
+   u32 ioport_addr = virtio_pci__port_addr(vpci);
+   u32 base_addr;
+
+   if (addr >= ioport_addr &&
+   addr < ioport_addr + pci__bar_size(>pci_hdr, 0))
+   base_addr = ioport_addr;
+   else
+   base_addr = virtio_pci__mmio_addr(vpci);
 
if (!is_write)
-   virtio_pci__data_in(vcpu, vdev, addr - mmio_addr, data, len);
+   virtio_pci__data_in(vcpu, vdev, addr - base_addr, data, len);
else
-   virtio_pci__data_out(vcpu, vdev, addr - mmio_addr, data, len);
+   virtio_pci__data_out(vcpu, vdev, addr - base_addr, data, len);
 }
 
 static int virtio_pci__bar_activate(struct kvm *kvm,
@@ -478,10 +462,8 @@ static int virtio_pci__bar_activate(struct kvm *kvm,
 
switch (bar_num) {
case 0:
-   r = ioport__register(kvm, bar_addr, _pci__io_ops,
-bar_size, vdev);
-   if (r > 0)
-   r = 0;
+   r = kvm__register_pio(kvm, bar_addr, bar_size,
+ virtio_pci__io_mmio_callback, vdev);
break;
case 1:
r =  kvm__register_mmio(kvm, bar_addr, bar_size, false,
@@ -510,7 +492,7 @@ static int virtio_pci__bar_deactivate(struct kvm *kvm,
 
switch (bar_num) {
case 0:
-   r = ioport__unregister(kvm, bar_addr);
+   r = kvm__deregister_pio(kvm, bar_addr);
break;
case 1:
case 2:
@@ -625,7 +607,7 @@ int virtio_pci__exit(struct kvm *kvm, struct virtio_device 
*vdev)
virtio_pci__reset(kvm, vdev);
kvm__deregister_mmio(kvm, virtio_pci__mmio_addr(vpci));
kvm__deregister_mmio(kvm, virtio_pci__msix_io_addr(vpci));
-   ioport__unregister(kvm, virtio_pci__port_addr(vpci));
+   kvm__deregister_pio(kvm, virtio_pci__port_addr(vpci));
 
return 0;
 }
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 16/22] vfio: Switch to new ioport trap handlers

2021-02-24 Thread Andre Przywara
Now that the vfio device has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 vfio/core.c | 37 ++---
 1 file changed, 10 insertions(+), 27 deletions(-)

diff --git a/vfio/core.c b/vfio/core.c
index ddd3c2c7..3ff2c0b0 100644
--- a/vfio/core.c
+++ b/vfio/core.c
@@ -81,7 +81,7 @@ out_free_buf:
return ret;
 }
 
-static bool _vfio_ioport_in(struct vfio_region *region, u32 offset,
+static bool vfio_ioport_in(struct vfio_region *region, u32 offset,
void *data, int len)
 {
struct vfio_device *vdev = region->vdev;
@@ -115,7 +115,7 @@ static bool _vfio_ioport_in(struct vfio_region *region, u32 
offset,
return true;
 }
 
-static bool _vfio_ioport_out(struct vfio_region *region, u32 offset,
+static bool vfio_ioport_out(struct vfio_region *region, u32 offset,
 void *data, int len)
 {
struct vfio_device *vdev = region->vdev;
@@ -155,30 +155,11 @@ static void vfio_ioport_mmio(struct kvm_cpu *vcpu, u64 
addr, u8 *data, u32 len,
u32 offset = addr - region->port_base;
 
if (is_write)
-   _vfio_ioport_out(region, offset, data, len);
+   vfio_ioport_out(region, offset, data, len);
else
-   _vfio_ioport_in(region, offset, data, len);
+   vfio_ioport_in(region, offset, data, len);
 }
 
-static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
-   u16 port, void *data, int len)
-{
-   vfio_ioport_mmio(vcpu, port, data, len, true, ioport->priv);
-   return true;
-}
-
-static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
-  u16 port, void *data, int len)
-{
-   vfio_ioport_mmio(vcpu, port, data, len, false, ioport->priv);
-   return true;
-}
-
-static struct ioport_operations vfio_ioport_ops = {
-   .io_in  = vfio_ioport_in,
-   .io_out = vfio_ioport_out,
-};
-
 static void vfio_mmio_access(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
 u8 is_write, void *ptr)
 {
@@ -223,9 +204,11 @@ static int vfio_setup_trap_region(struct kvm *kvm, struct 
vfio_device *vdev,
  struct vfio_region *region)
 {
if (region->is_ioport) {
-   int port = ioport__register(kvm, region->port_base,
-  _ioport_ops, region->info.size,
-  region);
+   int port;
+
+   port = kvm__register_pio(kvm, region->port_base,
+region->info.size, vfio_ioport_mmio,
+region);
if (port < 0)
return port;
return 0;
@@ -292,7 +275,7 @@ void vfio_unmap_region(struct kvm *kvm, struct vfio_region 
*region)
munmap(region->host_addr, region->info.size);
region->host_addr = NULL;
} else if (region->is_ioport) {
-   ioport__unregister(kvm, region->port_base);
+   kvm__deregister_pio(kvm, region->port_base);
} else {
kvm__deregister_mmio(kvm, region->guest_phys_addr);
}
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 14/22] hw/serial: Switch to new trap handlers

2021-02-24 Thread Andre Przywara
Now that the serial device has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/serial.c | 31 +++
 1 file changed, 3 insertions(+), 28 deletions(-)

diff --git a/hw/serial.c b/hw/serial.c
index c495eac1..4be188a1 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -392,26 +392,6 @@ static void serial8250_mmio(struct kvm_cpu *vcpu, u64 
addr, u8 *data, u32 len,
serial8250_in(dev, vcpu, addr - dev->iobase, data);
 }
 
-static bool serial8250_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
- u16 port, void *data, int size)
-{
-   struct serial8250_device *dev = ioport->priv;
-
-   serial8250_mmio(vcpu, port, data, 1, true, dev);
-
-   return true;
-}
-
-static bool serial8250_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
-u16 port, void *data, int size)
-{
-   struct serial8250_device *dev = ioport->priv;
-
-   serial8250_mmio(vcpu, port, data, 1, false, dev);
-
-   return true;
-}
-
 #ifdef CONFIG_HAS_LIBFDT
 
 char *fdt_stdout_path = NULL;
@@ -449,11 +429,6 @@ void serial8250_generate_fdt_node(void *fdt, struct 
device_header *dev_hdr,
 }
 #endif
 
-static struct ioport_operations serial8250_ops = {
-   .io_in  = serial8250_ioport_in,
-   .io_out = serial8250_ioport_out,
-};
-
 static int serial8250__device_init(struct kvm *kvm,
   struct serial8250_device *dev)
 {
@@ -464,7 +439,7 @@ static int serial8250__device_init(struct kvm *kvm,
return r;
 
ioport__map_irq(>irq);
-   r = ioport__register(kvm, dev->iobase, _ops, 8, dev);
+   r = kvm__register_pio(kvm, dev->iobase, 8, serial8250_mmio, dev);
 
return r;
 }
@@ -487,7 +462,7 @@ cleanup:
for (j = 0; j <= i; j++) {
struct serial8250_device *dev = [j];
 
-   ioport__unregister(kvm, dev->iobase);
+   kvm__deregister_pio(kvm, dev->iobase);
device__unregister(>dev_hdr);
}
 
@@ -503,7 +478,7 @@ int serial8250__exit(struct kvm *kvm)
for (i = 0; i < ARRAY_SIZE(devices); i++) {
struct serial8250_device *dev = [i];
 
-   r = ioport__unregister(kvm, dev->iobase);
+   r = kvm__deregister_pio(kvm, dev->iobase);
if (r < 0)
return r;
device__unregister(>dev_hdr);
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 15/22] vfio: Refactor ioport trap handler

2021-02-24 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Adjust the I/O port trap handler to use that new function, and provide
shims to implement the old ioport interface, for now.

Signed-off-by: Andre Przywara 
---
 vfio/core.c | 51 ---
 1 file changed, 36 insertions(+), 15 deletions(-)

diff --git a/vfio/core.c b/vfio/core.c
index 0b45e78b..ddd3c2c7 100644
--- a/vfio/core.c
+++ b/vfio/core.c
@@ -81,15 +81,12 @@ out_free_buf:
return ret;
 }
 
-static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
-  u16 port, void *data, int len)
+static bool _vfio_ioport_in(struct vfio_region *region, u32 offset,
+   void *data, int len)
 {
-   u32 val;
-   ssize_t nr;
-   struct vfio_region *region = ioport->priv;
struct vfio_device *vdev = region->vdev;
-
-   u32 offset = port - region->port_base;
+   ssize_t nr;
+   u32 val;
 
if (!(region->info.flags & VFIO_REGION_INFO_FLAG_READ))
return false;
@@ -97,7 +94,7 @@ static bool vfio_ioport_in(struct ioport *ioport, struct 
kvm_cpu *vcpu,
nr = pread(vdev->fd, , len, region->info.offset + offset);
if (nr != len) {
vfio_dev_err(vdev, "could not read %d bytes from I/O port 
0x%x\n",
-len, port);
+len, offset + region->port_base);
return false;
}
 
@@ -118,15 +115,13 @@ static bool vfio_ioport_in(struct ioport *ioport, struct 
kvm_cpu *vcpu,
return true;
 }
 
-static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
-   u16 port, void *data, int len)
+static bool _vfio_ioport_out(struct vfio_region *region, u32 offset,
+void *data, int len)
 {
-   u32 val;
-   ssize_t nr;
-   struct vfio_region *region = ioport->priv;
struct vfio_device *vdev = region->vdev;
+   ssize_t nr;
+   u32 val;
 
-   u32 offset = port - region->port_base;
 
if (!(region->info.flags & VFIO_REGION_INFO_FLAG_WRITE))
return false;
@@ -148,11 +143,37 @@ static bool vfio_ioport_out(struct ioport *ioport, struct 
kvm_cpu *vcpu,
nr = pwrite(vdev->fd, , len, region->info.offset + offset);
if (nr != len)
vfio_dev_err(vdev, "could not write %d bytes to I/O port 0x%x",
-len, port);
+len, offset + region->port_base);
 
return nr == len;
 }
 
+static void vfio_ioport_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+u8 is_write, void *ptr)
+{
+   struct vfio_region *region = ptr;
+   u32 offset = addr - region->port_base;
+
+   if (is_write)
+   _vfio_ioport_out(region, offset, data, len);
+   else
+   _vfio_ioport_in(region, offset, data, len);
+}
+
+static bool vfio_ioport_out(struct ioport *ioport, struct kvm_cpu *vcpu,
+   u16 port, void *data, int len)
+{
+   vfio_ioport_mmio(vcpu, port, data, len, true, ioport->priv);
+   return true;
+}
+
+static bool vfio_ioport_in(struct ioport *ioport, struct kvm_cpu *vcpu,
+  u16 port, void *data, int len)
+{
+   vfio_ioport_mmio(vcpu, port, data, len, false, ioport->priv);
+   return true;
+}
+
 static struct ioport_operations vfio_ioport_ops = {
.io_in  = vfio_ioport_in,
.io_out = vfio_ioport_out,
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 13/22] hw/serial: Refactor trap handler

2021-02-24 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO prototype.

Adjust the trap handler to use that new function, and provide shims to
implement the old ioport interface, for now.

We drop the usage of ioport__read8/write8 entirely, as this would only
be applicable for I/O port accesses, and does nothing for 8-bit wide
accesses anyway.

Signed-off-by: Andre Przywara 
---
 hw/serial.c | 93 +
 1 file changed, 58 insertions(+), 35 deletions(-)

diff --git a/hw/serial.c b/hw/serial.c
index b0465d99..c495eac1 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -242,36 +242,31 @@ void serial8250__inject_sysrq(struct kvm *kvm, char sysrq)
sysrq_pending = sysrq;
 }
 
-static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port,
-  void *data, int size)
+static bool serial8250_out(struct serial8250_device *dev, struct kvm_cpu *vcpu,
+  u16 offset, u8 data)
 {
-   struct serial8250_device *dev = ioport->priv;
-   u16 offset;
bool ret = true;
-   char *addr = data;
 
mutex_lock(>mutex);
 
-   offset = port - dev->iobase;
-
switch (offset) {
case UART_TX:
if (dev->lcr & UART_LCR_DLAB) {
-   dev->dll = ioport__read8(data);
+   dev->dll = data;
break;
}
 
/* Loopback mode */
if (dev->mcr & UART_MCR_LOOP) {
if (dev->rxcnt < FIFO_LEN) {
-   dev->rxbuf[dev->rxcnt++] = *addr;
+   dev->rxbuf[dev->rxcnt++] = data;
dev->lsr |= UART_LSR_DR;
}
break;
}
 
if (dev->txcnt < FIFO_LEN) {
-   dev->txbuf[dev->txcnt++] = *addr;
+   dev->txbuf[dev->txcnt++] = data;
dev->lsr &= ~UART_LSR_TEMT;
if (dev->txcnt == FIFO_LEN / 2)
dev->lsr &= ~UART_LSR_THRE;
@@ -283,18 +278,18 @@ static bool serial8250_out(struct ioport *ioport, struct 
kvm_cpu *vcpu, u16 port
break;
case UART_IER:
if (!(dev->lcr & UART_LCR_DLAB))
-   dev->ier = ioport__read8(data) & 0x0f;
+   dev->ier = data & 0x0f;
else
-   dev->dlm = ioport__read8(data);
+   dev->dlm = data;
break;
case UART_FCR:
-   dev->fcr = ioport__read8(data);
+   dev->fcr = data;
break;
case UART_LCR:
-   dev->lcr = ioport__read8(data);
+   dev->lcr = data;
break;
case UART_MCR:
-   dev->mcr = ioport__read8(data);
+   dev->mcr = data;
break;
case UART_LSR:
/* Factory test */
@@ -303,7 +298,7 @@ static bool serial8250_out(struct ioport *ioport, struct 
kvm_cpu *vcpu, u16 port
/* Not used */
break;
case UART_SCR:
-   dev->scr = ioport__read8(data);
+   dev->scr = data;
break;
default:
ret = false;
@@ -317,7 +312,7 @@ static bool serial8250_out(struct ioport *ioport, struct 
kvm_cpu *vcpu, u16 port
return ret;
 }
 
-static void serial8250_rx(struct serial8250_device *dev, void *data)
+static void serial8250_rx(struct serial8250_device *dev, u8 *data)
 {
if (dev->rxdone == dev->rxcnt)
return;
@@ -325,57 +320,54 @@ static void serial8250_rx(struct serial8250_device *dev, 
void *data)
/* Break issued ? */
if (dev->lsr & UART_LSR_BI) {
dev->lsr &= ~UART_LSR_BI;
-   ioport__write8(data, 0);
+   *data = 0;
return;
}
 
-   ioport__write8(data, dev->rxbuf[dev->rxdone++]);
+   *data = dev->rxbuf[dev->rxdone++];
if (dev->rxcnt == dev->rxdone) {
dev->lsr &= ~UART_LSR_DR;
dev->rxcnt = dev->rxdone = 0;
}
 }
 
-static bool serial8250_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
+static bool serial8250_in(struct serial8250_device *dev, struct kvm_cpu *vcpu,
+ u16 offset, u8 *data)
 {
-   struct serial8250_device *dev = ioport->priv;
-   u16 offset;
bool ret = true;
 
mutex_lock(>mutex);
 
-   offset = port - dev->iobase;
-
switch (offset) {
case UART_RX:
  

[PATCH kvmtool v2 12/22] hw/vesa: Switch trap handling to use MMIO handler

2021-02-24 Thread Andre Przywara
To be able to use the VESA device with the new generic I/O trap handler,
we need to use the different MMIO handler callback routine.

Replace the existing dummy in and out handlers with a joint dummy
MMIO handler, and register this using the new registration function.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/vesa.c | 19 +--
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/hw/vesa.c b/hw/vesa.c
index 8659a002..7f82cdb4 100644
--- a/hw/vesa.c
+++ b/hw/vesa.c
@@ -43,21 +43,11 @@ static struct framebuffer vesafb = {
.mem_size   = VESA_MEM_SIZE,
 };
 
-static bool vesa_pci_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
+static void vesa_pci_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+   u8 is_write, void *ptr)
 {
-   return true;
 }
 
-static bool vesa_pci_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
-{
-   return true;
-}
-
-static struct ioport_operations vesa_io_ops = {
-   .io_in  = vesa_pci_io_in,
-   .io_out = vesa_pci_io_out,
-};
-
 static int vesa__bar_activate(struct kvm *kvm, struct pci_device_header 
*pci_hdr,
  int bar_num, void *data)
 {
@@ -82,7 +72,8 @@ struct framebuffer *vesa__init(struct kvm *kvm)
BUILD_BUG_ON(VESA_MEM_SIZE < VESA_BPP/8 * VESA_WIDTH * VESA_HEIGHT);
 
vesa_base_addr = pci_get_io_port_block(PCI_IO_SIZE);
-   r = ioport__register(kvm, vesa_base_addr, _io_ops, PCI_IO_SIZE, 
NULL);
+   r = kvm__register_pio(kvm, vesa_base_addr, PCI_IO_SIZE, vesa_pci_io,
+ NULL);
if (r < 0)
goto out_error;
 
@@ -116,7 +107,7 @@ unmap_dev:
 unregister_device:
device__unregister(_device);
 unregister_ioport:
-   ioport__unregister(kvm, vesa_base_addr);
+   kvm__deregister_pio(kvm, vesa_base_addr);
 out_error:
return ERR_PTR(r);
 }
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 11/22] hw/rtc: Switch to new trap handler

2021-02-24 Thread Andre Przywara
Now that the RTC device has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/rtc.c | 21 ++---
 1 file changed, 2 insertions(+), 19 deletions(-)

diff --git a/hw/rtc.c b/hw/rtc.c
index 664d4cb0..ee4c9102 100644
--- a/hw/rtc.c
+++ b/hw/rtc.c
@@ -120,23 +120,6 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 
*data,
}
 }
 
-static bool cmos_ram_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size)
-{
-   cmos_ram_io(vcpu, port, data, size, false, NULL);
-   return true;
-}
-
-static bool cmos_ram_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
-{
-   cmos_ram_io(vcpu, port, data, size, true, NULL);
-   return true;
-}
-
-static struct ioport_operations cmos_ram_ioport_ops = {
-   .io_out = cmos_ram_out,
-   .io_in  = cmos_ram_in,
-};
-
 #ifdef CONFIG_HAS_LIBFDT
 static void generate_rtc_fdt_node(void *fdt,
  struct device_header *dev_hdr,
@@ -169,7 +152,7 @@ int rtc__init(struct kvm *kvm)
return r;
 
/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-   r = ioport__register(kvm, 0x0070, _ram_ioport_ops, 2, NULL);
+   r = kvm__register_pio(kvm, 0x0070, 2, cmos_ram_io, NULL);
if (r < 0)
goto out_device;
 
@@ -188,7 +171,7 @@ dev_init(rtc__init);
 int rtc__exit(struct kvm *kvm)
 {
/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-   ioport__unregister(kvm, 0x0070);
+   kvm__deregister_pio(kvm, 0x0070);
 
return 0;
 }
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 10/22] hw/rtc: Refactor trap handlers

2021-02-24 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide emulation functions compatible with the MMIO prototype.

Merge the two different trap handlers into one function, checking for
read/write and data/index register inside.
Adjust the trap handlers to use that new function, and provide shims to
implement the old ioport interface, for now.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/rtc.c | 70 
 1 file changed, 35 insertions(+), 35 deletions(-)

diff --git a/hw/rtc.c b/hw/rtc.c
index 5483879f..664d4cb0 100644
--- a/hw/rtc.c
+++ b/hw/rtc.c
@@ -42,11 +42,37 @@ static inline unsigned char bin2bcd(unsigned val)
return ((val / 10) << 4) + val % 10;
 }
 
-static bool cmos_ram_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
+static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+   u32 len, u8 is_write, void *ptr)
 {
struct tm *tm;
time_t ti;
 
+   if (is_write) {
+   if (addr == 0x70) { /* index register */
+   u8 value = ioport__read8(data);
+
+   vcpu->kvm->nmi_disabled = value & (1UL << 7);
+   rtc.cmos_idx= value & ~(1UL << 7);
+
+   return;
+   }
+
+   switch (rtc.cmos_idx) {
+   case RTC_REG_C:
+   case RTC_REG_D:
+   /* Read-only */
+   break;
+   default:
+   rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data);
+   break;
+   }
+   return;
+   }
+
+   if (addr == 0x70)
+   return;
+
time();
 
tm = gmtime();
@@ -92,42 +118,23 @@ static bool cmos_ram_data_in(struct ioport *ioport, struct 
kvm_cpu *vcpu, u16 po
ioport__write8(data, rtc.cmos_data[rtc.cmos_idx]);
break;
}
-
-   return true;
 }
 
-static bool cmos_ram_data_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
+static bool cmos_ram_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size)
 {
-   switch (rtc.cmos_idx) {
-   case RTC_REG_C:
-   case RTC_REG_D:
-   /* Read-only */
-   break;
-   default:
-   rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data);
-   break;
-   }
-
+   cmos_ram_io(vcpu, port, data, size, false, NULL);
return true;
 }
 
-static struct ioport_operations cmos_ram_data_ioport_ops = {
-   .io_out = cmos_ram_data_out,
-   .io_in  = cmos_ram_data_in,
-};
-
-static bool cmos_ram_index_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
+static bool cmos_ram_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
 {
-   u8 value = ioport__read8(data);
-
-   vcpu->kvm->nmi_disabled = value & (1UL << 7);
-   rtc.cmos_idx= value & ~(1UL << 7);
-
+   cmos_ram_io(vcpu, port, data, size, true, NULL);
return true;
 }
 
-static struct ioport_operations cmos_ram_index_ioport_ops = {
-   .io_out = cmos_ram_index_out,
+static struct ioport_operations cmos_ram_ioport_ops = {
+   .io_out = cmos_ram_out,
+   .io_in  = cmos_ram_in,
 };
 
 #ifdef CONFIG_HAS_LIBFDT
@@ -162,21 +169,15 @@ int rtc__init(struct kvm *kvm)
return r;
 
/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
-   r = ioport__register(kvm, 0x0070, _ram_index_ioport_ops, 1, NULL);
+   r = ioport__register(kvm, 0x0070, _ram_ioport_ops, 2, NULL);
if (r < 0)
goto out_device;
 
-   r = ioport__register(kvm, 0x0071, _ram_data_ioport_ops, 1, NULL);
-   if (r < 0)
-   goto out_ioport;
-
/* Set the VRT bit in Register D to indicate valid RAM and time */
rtc.cmos_data[RTC_REG_D] = RTC_REG_D_VRT;
 
return r;
 
-out_ioport:
-   ioport__unregister(kvm, 0x0070);
 out_device:
device__unregister(_dev_hdr);
 
@@ -188,7 +189,6 @@ int rtc__exit(struct kvm *kvm)
 {
/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
ioport__unregister(kvm, 0x0070);
-   ioport__unregister(kvm, 0x0071);
 
return 0;
 }
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 09/22] x86/ioport: Switch to new trap handlers

2021-02-24 Thread Andre Przywara
Now that the x86 I/O ports have trap handlers adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Since the debug output was done in ioport.c, we would lose this
functionality when moving over to the MMIO handlers. So bring this back
here explicitly, by introducing debug_mmio().

Signed-off-by: Andre Przywara 
---
 x86/ioport.c | 102 +++
 1 file changed, 37 insertions(+), 65 deletions(-)

diff --git a/x86/ioport.c b/x86/ioport.c
index 78f9a863..9fcbb6c9 100644
--- a/x86/ioport.c
+++ b/x86/ioport.c
@@ -3,21 +3,35 @@
 #include 
 #include 
 
-static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+static void debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
   u8 is_write, void *ptr)
 {
+   if (!vcpu->kvm->cfg.ioport_debug)
+   return;
+
+   fprintf(stderr, "debug port %s from VCPU%lu: port=0x%lx, size=%u",
+   is_write ? "write" : "read", vcpu->cpu_id,
+   (unsigned long)addr, len);
+   if (is_write) {
+   u32 value;
+
+   switch (len) {
+   case 1: value = ioport__read8(data); break;
+   case 2: value = ioport__read16((u16*)data); break;
+   case 4: value = ioport__read32((u32*)data); break;
+   default: value = 0; break;
+   }
+   fprintf(stderr, ", data: 0x%x\n", value);
+   } else {
+   fprintf(stderr, "\n");
+   }
 }
 
-static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
+static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+  u8 is_write, void *ptr)
 {
-   dummy_mmio(vcpu, port, data, size, true, NULL);
-   return 0;
 }
 
-static struct ioport_operations debug_ops = {
-   .io_out = debug_io_out,
-};
-
 static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
   u32 len, u8 is_write, void *ptr)
 {
@@ -31,37 +45,6 @@ static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 
addr, u8 *data,
putchar(ch);
 }
 
-static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
-{
-   seabios_debug_mmio(vcpu, port, data, size, true, NULL);
-   return 0;
-}
-
-static struct ioport_operations seabios_debug_ops = {
-   .io_out = seabios_debug_io_out,
-};
-
-static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size)
-{
-   dummy_mmio(vcpu, port, data, size, false, NULL);
-   return true;
-}
-
-static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
-{
-   dummy_mmio(vcpu, port, data, size, true, NULL);
-   return true;
-}
-
-static struct ioport_operations dummy_read_write_ioport_ops = {
-   .io_in  = dummy_io_in,
-   .io_out = dummy_io_out,
-};
-
-static struct ioport_operations dummy_write_only_ioport_ops = {
-   .io_out = dummy_io_out,
-};
-
 /*
  * The "fast A20 gate"
  */
@@ -76,17 +59,6 @@ static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, 
u8 *data, u32 len,
ioport__write8(data, 0x02);
 }
 
-static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
-{
-   ps2_control_mmio(vcpu, port, data, size, false, NULL);
-   return true;
-}
-
-static struct ioport_operations ps2_control_a_ops = {
-   .io_in  = ps2_control_a_io_in,
-   .io_out = dummy_io_out,
-};
-
 void ioport__map_irq(u8 *irq)
 {
 }
@@ -98,75 +70,75 @@ static int ioport__setup_arch(struct kvm *kvm)
/* Legacy ioport setup */
 
/*  - 001F - DMA1 controller */
-   r = ioport__register(kvm, 0x, _read_write_ioport_ops, 32, 
NULL);
+   r = kvm__register_pio(kvm, 0x, 32, dummy_mmio, NULL);
if (r < 0)
return r;
 
/* 0x0020 - 0x003F - 8259A PIC 1 */
-   r = ioport__register(kvm, 0x0020, _read_write_ioport_ops, 2, 
NULL);
+   r = kvm__register_pio(kvm, 0x0020, 2, dummy_mmio, NULL);
if (r < 0)
return r;
 
/* PORT 0040-005F - PIT - PROGRAMMABLE INTERVAL TIMER (8253, 8254) */
-   r = ioport__register(kvm, 0x0040, _read_write_ioport_ops, 4, 
NULL);
+   r = kvm__register_pio(kvm, 0x0040, 4, dummy_mmio, NULL);
if (r < 0)
return r;
 
/* 0092 - PS/2 system control port A */
-   r = ioport__register(kvm, 0x0092, _control_a_ops, 1, NULL);
+   r = kvm__register_pio(kvm, 0x0092, 1, ps2_control_mmio, NULL);
if (r < 0)
return r;
 
/* 0x00A0 - 0x00AF - 8259A PIC 2 */
-

[PATCH kvmtool v2 08/22] x86/ioport: Refactor trap handlers

2021-02-24 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide emulation functions compatible with the MMIO
prototype.

Adjust the trap handlers to use that new function, and provide shims to
implement the old ioport interface, for now.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 x86/ioport.c | 30 ++
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/x86/ioport.c b/x86/ioport.c
index a8d2bb1a..78f9a863 100644
--- a/x86/ioport.c
+++ b/x86/ioport.c
@@ -3,8 +3,14 @@
 #include 
 #include 
 
+static void dummy_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+  u8 is_write, void *ptr)
+{
+}
+
 static bool debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
 {
+   dummy_mmio(vcpu, port, data, size, true, NULL);
return 0;
 }
 
@@ -12,15 +18,23 @@ static struct ioport_operations debug_ops = {
.io_out = debug_io_out,
 };
 
-static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
+static void seabios_debug_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+  u32 len, u8 is_write, void *ptr)
 {
char ch;
 
+   if (!is_write)
+   return;
+
ch = ioport__read8(data);
 
putchar(ch);
+}
 
-   return true;
+static bool seabios_debug_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
+{
+   seabios_debug_mmio(vcpu, port, data, size, true, NULL);
+   return 0;
 }
 
 static struct ioport_operations seabios_debug_ops = {
@@ -29,11 +43,13 @@ static struct ioport_operations seabios_debug_ops = {
 
 static bool dummy_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size)
 {
+   dummy_mmio(vcpu, port, data, size, false, NULL);
return true;
 }
 
 static bool dummy_io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 
port, void *data, int size)
 {
+   dummy_mmio(vcpu, port, data, size, true, NULL);
return true;
 }
 
@@ -50,13 +66,19 @@ static struct ioport_operations dummy_write_only_ioport_ops 
= {
  * The "fast A20 gate"
  */
 
-static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
+static void ps2_control_mmio(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+u8 is_write, void *ptr)
 {
/*
 * A20 is always enabled.
 */
-   ioport__write8(data, 0x02);
+   if (!is_write)
+   ioport__write8(data, 0x02);
+}
 
+static bool ps2_control_a_io_in(struct ioport *ioport, struct kvm_cpu *vcpu, 
u16 port, void *data, int size)
+{
+   ps2_control_mmio(vcpu, port, data, size, false, NULL);
return true;
 }
 
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 07/22] hw/i8042: Switch to new trap handlers

2021-02-24 Thread Andre Przywara
Now that the PC keyboard has a trap handler adhering to the MMIO fault
handler prototype, let's switch over to the joint registration routine.

This allows us to get rid of the ioport shim routines.

Make the kbd_init() function static on the way.

Signed-off-by: Andre Przywara 
---
 hw/i8042.c  | 30 --
 include/kvm/i8042.h |  1 -
 2 files changed, 4 insertions(+), 27 deletions(-)

diff --git a/hw/i8042.c b/hw/i8042.c
index ab82..20be36c4 100644
--- a/hw/i8042.c
+++ b/hw/i8042.c
@@ -325,40 +325,18 @@ static void kbd_io(struct kvm_cpu *vcpu, u64 addr, u8 
*data, u32 len,
ioport__write8(data, value);
 }
 
-/*
- * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
- */
-static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void 
*data, int size)
-{
-   kbd_io(vcpu, port, data, size, false, NULL);
-
-   return true;
-}
-
-static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size)
-{
-   kbd_io(vcpu, port, data, size, true, NULL);
-
-   return true;
-}
-
-static struct ioport_operations kbd_ops = {
-   .io_in  = kbd_in,
-   .io_out = kbd_out,
-};
-
-int kbd__init(struct kvm *kvm)
+static int kbd__init(struct kvm *kvm)
 {
int r;
 
kbd_reset();
state.kvm = kvm;
-   r = ioport__register(kvm, I8042_DATA_REG, _ops, 2, NULL);
+   r = kvm__register_pio(kvm, I8042_DATA_REG, 2, kbd_io, NULL);
if (r < 0)
return r;
-   r = ioport__register(kvm, I8042_COMMAND_REG, _ops, 2, NULL);
+   r = kvm__register_pio(kvm, I8042_COMMAND_REG, 2, kbd_io, NULL);
if (r < 0) {
-   ioport__unregister(kvm, I8042_DATA_REG);
+   kvm__deregister_pio(kvm, I8042_DATA_REG);
return r;
}
 
diff --git a/include/kvm/i8042.h b/include/kvm/i8042.h
index 3b4ab688..cd4ae6bb 100644
--- a/include/kvm/i8042.h
+++ b/include/kvm/i8042.h
@@ -7,6 +7,5 @@ struct kvm;
 
 void mouse_queue(u8 c);
 void kbd_queue(u8 c);
-int kbd__init(struct kvm *kvm);
 
 #endif
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 06/22] hw/i8042: Refactor trap handler

2021-02-24 Thread Andre Przywara
With the planned retirement of the special ioport emulation code, we
need to provide an emulation function compatible with the MMIO
prototype.

Adjust the trap handler to use that new function, and provide shims to
implement the old ioport interface, for now.

Signed-off-by: Andre Przywara 
---
 hw/i8042.c | 68 +++---
 1 file changed, 34 insertions(+), 34 deletions(-)

diff --git a/hw/i8042.c b/hw/i8042.c
index 7d1f9772..ab82 100644
--- a/hw/i8042.c
+++ b/hw/i8042.c
@@ -292,52 +292,52 @@ static void kbd_reset(void)
};
 }
 
-/*
- * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
- */
-static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void 
*data, int size)
+static void kbd_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, u32 len,
+  u8 is_write, void *ptr)
 {
-   switch (port) {
-   case I8042_COMMAND_REG: {
-   u8 value = kbd_read_status();
-   ioport__write8(data, value);
+   u8 value;
+
+   if (is_write)
+   value = ioport__read8(data);
+
+   switch (addr) {
+   case I8042_COMMAND_REG:
+   if (is_write)
+   kbd_write_command(vcpu->kvm, value);
+   else
+   value = kbd_read_status();
break;
-   }
-   case I8042_DATA_REG: {
-   u8 value = kbd_read_data();
-   ioport__write8(data, value);
+   case I8042_DATA_REG:
+   if (is_write)
+   kbd_write_data(value);
+   else
+   value = kbd_read_data();
break;
-   }
-   case I8042_PORT_B_REG: {
-   ioport__write8(data, 0x20);
+   case I8042_PORT_B_REG:
+   if (!is_write)
+   value = 0x20;
break;
-   }
default:
-   return false;
+   return;
}
 
+   if (!is_write)
+   ioport__write8(data, value);
+}
+
+/*
+ * Called when the OS has written to one of the keyboard's ports (0x60 or 0x64)
+ */
+static bool kbd_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void 
*data, int size)
+{
+   kbd_io(vcpu, port, data, size, 0, NULL);
+
return true;
 }
 
 static bool kbd_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size)
 {
-   switch (port) {
-   case I8042_COMMAND_REG: {
-   u8 value = ioport__read8(data);
-   kbd_write_command(vcpu->kvm, value);
-   break;
-   }
-   case I8042_DATA_REG: {
-   u8 value = ioport__read8(data);
-   kbd_write_data(value);
-   break;
-   }
-   case I8042_PORT_B_REG: {
-   break;
-   }
-   default:
-   return false;
-   }
+   kbd_io(vcpu, port, data, size, 1, NULL);
 
return true;
 }
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 05/22] hw/i8042: Clean up data types

2021-02-24 Thread Andre Przywara
The i8042 is clearly an 8-bit era device, so there is little room for
32-bit registers.
Clean up the data types used.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/i8042.c | 26 +-
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/hw/i8042.c b/hw/i8042.c
index 37a99a2d..7d1f9772 100644
--- a/hw/i8042.c
+++ b/hw/i8042.c
@@ -64,11 +64,11 @@
 struct kbd_state {
struct kvm  *kvm;
 
-   charkq[QUEUE_SIZE]; /* Keyboard queue */
+   u8  kq[QUEUE_SIZE]; /* Keyboard queue */
int kread, kwrite;  /* Indexes into the queue */
int kcount; /* number of elements in queue 
*/
 
-   charmq[QUEUE_SIZE];
+   u8  mq[QUEUE_SIZE];
int mread, mwrite;
int mcount;
 
@@ -82,7 +82,7 @@ struct kbd_state {
 * Some commands (on port 0x64) have arguments;
 * we store the command here while we wait for the argument
 */
-   u32 write_cmd;
+   u8  write_cmd;
 };
 
 static struct kbd_statestate;
@@ -173,9 +173,9 @@ static void kbd_write_command(struct kvm *kvm, u8 val)
 /*
  * Called when the OS reads from port 0x60 (PS/2 data)
  */
-static u32 kbd_read_data(void)
+static u8 kbd_read_data(void)
 {
-   u32 ret;
+   u8 ret;
int i;
 
if (state.kcount != 0) {
@@ -202,9 +202,9 @@ static u32 kbd_read_data(void)
 /*
  * Called when the OS read from port 0x64, the command port
  */
-static u32 kbd_read_status(void)
+static u8 kbd_read_status(void)
 {
-   return (u32)state.status;
+   return state.status;
 }
 
 /*
@@ -212,7 +212,7 @@ static u32 kbd_read_status(void)
  * Things written here are generally arguments to commands previously
  * written to port 0x64 and stored in state.write_cmd
  */
-static void kbd_write_data(u32 val)
+static void kbd_write_data(u8 val)
 {
switch (state.write_cmd) {
case I8042_CMD_CTL_WCTR:
@@ -266,8 +266,8 @@ static void kbd_write_data(u32 val)
break;
default:
break;
-   }
-   break;
+   }
+   break;
case 0:
/* Just send the ID */
kbd_queue(RESPONSE_ACK);
@@ -304,8 +304,8 @@ static bool kbd_in(struct ioport *ioport, struct kvm_cpu 
*vcpu, u16 port, void *
break;
}
case I8042_DATA_REG: {
-   u32 value = kbd_read_data();
-   ioport__write32(data, value);
+   u8 value = kbd_read_data();
+   ioport__write8(data, value);
break;
}
case I8042_PORT_B_REG: {
@@ -328,7 +328,7 @@ static bool kbd_out(struct ioport *ioport, struct kvm_cpu 
*vcpu, u16 port, void
break;
}
case I8042_DATA_REG: {
-   u32 value = ioport__read32(data);
+   u8 value = ioport__read8(data);
kbd_write_data(value);
break;
}
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 04/22] mmio: Extend handling to include ioport emulation

2021-02-24 Thread Andre Przywara
In their core functionality MMIO and I/O port traps are not really
different, yet we still have two totally separate code paths for
handling them. Devices need to decide on one conduit or need to provide
different handler functions for each of them.

Extend the existing MMIO emulation to also cover ioport handlers.
This just adds another RB tree root for holding the I/O port handlers,
but otherwise uses the same tree population and lookup code.
"ioport" or "mmio" just become a flag in the registration function.
Provide wrappers to not break existing users, and allow an easy
transition for the existing ioport handlers.

This also means that ioport handlers now can use the same emulation
callback prototype as MMIO handlers, which means we have to migrate them
over. To allow a smooth transition, we hook up the new I/O emulate
function to the end of the existing ioport emulation code.

Signed-off-by: Andre Przywara 
---
 include/kvm/kvm.h | 49 ---
 ioport.c  |  4 +--
 mmio.c| 65 +++
 3 files changed, 102 insertions(+), 16 deletions(-)

diff --git a/include/kvm/kvm.h b/include/kvm/kvm.h
index f1f0afd7..306b258a 100644
--- a/include/kvm/kvm.h
+++ b/include/kvm/kvm.h
@@ -27,10 +27,23 @@
 #define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
 #endif
 
+/*
+ * We are reusing the existing DEVICE_BUS_MMIO and DEVICE_BUS_IOPORT constants
+ * from kvm/devices.h to differentiate between registering an I/O port and an
+ * MMIO region.
+ * To avoid collisions with future additions of more bus types, we reserve
+ * a generous 4 bits for the bus mask here.
+ */
+#define IOTRAP_BUS_MASK0xf
+#define IOTRAP_COALESCE(1U << 4)
+
 #define DEFINE_KVM_EXT(ext)\
.name = #ext,   \
.code = ext
 
+struct kvm_cpu;
+typedef void (*mmio_handler_fn)(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+   u32 len, u8 is_write, void *ptr);
 typedef void (*fdt_irq_fn)(void *fdt, u8 irq, enum irq_type irq_type);
 
 enum {
@@ -113,6 +126,8 @@ void kvm__irq_line(struct kvm *kvm, int irq, int level);
 void kvm__irq_trigger(struct kvm *kvm, int irq);
 bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void *data, int 
direction, int size, u32 count);
 bool kvm__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr, u8 *data, u32 len, 
u8 is_write);
+bool kvm__emulate_pio(struct kvm_cpu *vcpu, u16 port, void *data,
+ int direction, int size, u32 count);
 int kvm__destroy_mem(struct kvm *kvm, u64 guest_phys, u64 size, void 
*userspace_addr);
 int kvm__register_mem(struct kvm *kvm, u64 guest_phys, u64 size, void 
*userspace_addr,
  enum kvm_mem_type type);
@@ -136,10 +151,36 @@ static inline int kvm__reserve_mem(struct kvm *kvm, u64 
guest_phys, u64 size)
 KVM_MEM_TYPE_RESERVED);
 }
 
-int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr, u64 
phys_addr_len, bool coalesce,
-   void (*mmio_fn)(struct kvm_cpu *vcpu, u64 
addr, u8 *data, u32 len, u8 is_write, void *ptr),
-   void *ptr);
-bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr);
+int __must_check kvm__register_iotrap(struct kvm *kvm, u64 phys_addr, u64 len,
+ mmio_handler_fn mmio_fn, void *ptr,
+ unsigned int flags);
+
+static inline
+int __must_check kvm__register_mmio(struct kvm *kvm, u64 phys_addr,
+   u64 phys_addr_len, bool coalesce,
+   mmio_handler_fn mmio_fn, void *ptr)
+{
+   return kvm__register_iotrap(kvm, phys_addr, phys_addr_len, mmio_fn, ptr,
+   DEVICE_BUS_MMIO | (coalesce ? IOTRAP_COALESCE : 0));
+}
+static inline
+int __must_check kvm__register_pio(struct kvm *kvm, u16 port, u16 len,
+  mmio_handler_fn mmio_fn, void *ptr)
+{
+   return kvm__register_iotrap(kvm, port, len, mmio_fn, ptr,
+   DEVICE_BUS_IOPORT);
+}
+
+bool kvm__deregister_iotrap(struct kvm *kvm, u64 phys_addr, unsigned int 
flags);
+static inline bool kvm__deregister_mmio(struct kvm *kvm, u64 phys_addr)
+{
+   return kvm__deregister_iotrap(kvm, phys_addr, DEVICE_BUS_MMIO);
+}
+static inline bool kvm__deregister_pio(struct kvm *kvm, u16 port)
+{
+   return kvm__deregister_iotrap(kvm, port, DEVICE_BUS_IOPORT);
+}
+
 void kvm__reboot(struct kvm *kvm);
 void kvm__pause(struct kvm *kvm);
 void kvm__continue(struct kvm *kvm);
diff --git a/ioport.c b/ioport.c
index e0123f27..ce29e7e7 100644
--- a/ioport.c
+++ b/ioport.c
@@ -162,7 +162,8 @@ bool kvm__emulate_io(struct kvm_cpu *vcpu, u16 port, void 
*data, int direction,
 
entry = ioport_get(_tree, port);
if (!entry)
-   goto out;
+   return k

[PATCH kvmtool v2 03/22] ioport: Retire .generate_fdt_node functionality

2021-02-24 Thread Andre Przywara
The ioport routines support a special way of registering FDT node
generator functions. There is no reason to have this separate from the
already existing way via the device header.

Now that the only user of this special ioport variety has been
transferred, we can retire this code, to simplify ioport handling.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 include/kvm/ioport.h |  4 
 ioport.c | 34 --
 2 files changed, 38 deletions(-)

diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
index d0213541..a61038e2 100644
--- a/include/kvm/ioport.h
+++ b/include/kvm/ioport.h
@@ -29,10 +29,6 @@ struct ioport {
 struct ioport_operations {
bool (*io_in)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size);
bool (*io_out)(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, 
void *data, int size);
-   void (*generate_fdt_node)(struct ioport *ioport, void *fdt,
- void (*generate_irq_prop)(void *fdt,
-   u8 irq,
-   enum irq_type));
 };
 
 void ioport__map_irq(u8 *irq);
diff --git a/ioport.c b/ioport.c
index a6972179..e0123f27 100644
--- a/ioport.c
+++ b/ioport.c
@@ -56,7 +56,6 @@ static struct ioport *ioport_get(struct rb_root *root, u64 
addr)
 /* Called with ioport_lock held. */
 static void ioport_unregister(struct rb_root *root, struct ioport *data)
 {
-   device__unregister(>dev_hdr);
ioport_remove(root, data);
free(data);
 }
@@ -70,30 +69,6 @@ static void ioport_put(struct rb_root *root, struct ioport 
*data)
mutex_unlock(_lock);
 }
 
-#ifdef CONFIG_HAS_LIBFDT
-static void generate_ioport_fdt_node(void *fdt,
-struct device_header *dev_hdr,
-void (*generate_irq_prop)(void *fdt,
-  u8 irq,
-  enum irq_type))
-{
-   struct ioport *ioport = container_of(dev_hdr, struct ioport, dev_hdr);
-   struct ioport_operations *ops = ioport->ops;
-
-   if (ops->generate_fdt_node)
-   ops->generate_fdt_node(ioport, fdt, generate_irq_prop);
-}
-#else
-static void generate_ioport_fdt_node(void *fdt,
-struct device_header *dev_hdr,
-void (*generate_irq_prop)(void *fdt,
-  u8 irq,
-  enum irq_type))
-{
-   die("Unable to generate device tree nodes without libfdt\n");
-}
-#endif
-
 int ioport__register(struct kvm *kvm, u16 port, struct ioport_operations *ops, 
int count, void *param)
 {
struct ioport *entry;
@@ -107,10 +82,6 @@ int ioport__register(struct kvm *kvm, u16 port, struct 
ioport_operations *ops, i
.node   = RB_INT_INIT(port, port + count),
.ops= ops,
.priv   = param,
-   .dev_hdr= (struct device_header) {
-   .bus_type   = DEVICE_BUS_IOPORT,
-   .data   = generate_ioport_fdt_node,
-   },
/*
 * Start from 0 because ioport__unregister() doesn't decrement
 * the reference count.
@@ -123,15 +94,10 @@ int ioport__register(struct kvm *kvm, u16 port, struct 
ioport_operations *ops, i
r = ioport_insert(_tree, entry);
if (r < 0)
goto out_free;
-   r = device__register(>dev_hdr);
-   if (r < 0)
-   goto out_remove;
mutex_unlock(_lock);
 
return port;
 
-out_remove:
-   ioport_remove(_tree, entry);
 out_free:
free(entry);
mutex_unlock(_lock);
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 02/22] hw/serial: Use device abstraction for FDT generator function

2021-02-24 Thread Andre Przywara
At the moment we use the .generate_fdt_node member of the ioport ops
structure to store the function pointer for the FDT node generator
function. ioport__register() will then put a wrapper and this pointer
into the device header.
The serial device is the only device making use of this special ioport
feature, so let's move this over to using the device header directly.

This will allow us to get rid of this .generate_fdt_node member in the
ops and simplify the code.

Signed-off-by: Andre Przywara 
Reviewed-by: Alexandru Elisei 
---
 hw/serial.c   | 49 +--
 include/kvm/kvm.h |  2 ++
 2 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/hw/serial.c b/hw/serial.c
index 13c4663e..b0465d99 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -23,6 +23,7 @@
 #define UART_IIR_TYPE_BITS 0xc0
 
 struct serial8250_device {
+   struct device_headerdev_hdr;
struct mutexmutex;
u8  id;
 
@@ -53,9 +54,20 @@ struct serial8250_device {
.msr= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS, \
.mcr= UART_MCR_OUT2,
 
+#ifdef CONFIG_HAS_LIBFDT
+static
+void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
+ fdt_irq_fn irq_fn);
+#else
+#define serial8250_generate_fdt_node   NULL
+#endif
 static struct serial8250_device devices[] = {
/* ttyS0 */
[0] = {
+   .dev_hdr = {
+   .bus_type   = DEVICE_BUS_IOPORT,
+   .data   = serial8250_generate_fdt_node,
+   },
.mutex  = MUTEX_INITIALIZER,
 
.id = 0,
@@ -66,6 +78,10 @@ static struct serial8250_device devices[] = {
},
/* ttyS1 */
[1] = {
+   .dev_hdr = {
+   .bus_type   = DEVICE_BUS_IOPORT,
+   .data   = serial8250_generate_fdt_node,
+   },
.mutex  = MUTEX_INITIALIZER,
 
.id = 1,
@@ -76,6 +92,10 @@ static struct serial8250_device devices[] = {
},
/* ttyS2 */
[2] = {
+   .dev_hdr = {
+   .bus_type   = DEVICE_BUS_IOPORT,
+   .data   = serial8250_generate_fdt_node,
+   },
.mutex  = MUTEX_INITIALIZER,
 
.id = 2,
@@ -86,6 +106,10 @@ static struct serial8250_device devices[] = {
},
/* ttyS3 */
[3] = {
+   .dev_hdr = {
+   .bus_type   = DEVICE_BUS_IOPORT,
+   .data   = serial8250_generate_fdt_node,
+   },
.mutex  = MUTEX_INITIALIZER,
 
.id = 3,
@@ -371,13 +395,14 @@ char *fdt_stdout_path = NULL;
 
 #define DEVICE_NAME_MAX_LEN 32
 static
-void serial8250_generate_fdt_node(struct ioport *ioport, void *fdt,
- void (*generate_irq_prop)(void *fdt,
-   u8 irq,
-   enum irq_type))
+void serial8250_generate_fdt_node(void *fdt, struct device_header *dev_hdr,
+ fdt_irq_fn irq_fn)
 {
char dev_name[DEVICE_NAME_MAX_LEN];
-   struct serial8250_device *dev = ioport->priv;
+   struct serial8250_device *dev = container_of(dev_hdr,
+struct serial8250_device,
+dev_hdr);
+
u64 addr = KVM_IOPORT_AREA + dev->iobase;
u64 reg_prop[] = {
cpu_to_fdt64(addr),
@@ -395,24 +420,26 @@ void serial8250_generate_fdt_node(struct ioport *ioport, 
void *fdt,
_FDT(fdt_begin_node(fdt, dev_name));
_FDT(fdt_property_string(fdt, "compatible", "ns16550a"));
_FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop)));
-   generate_irq_prop(fdt, dev->irq, IRQ_TYPE_LEVEL_HIGH);
+   irq_fn(fdt, dev->irq, IRQ_TYPE_LEVEL_HIGH);
_FDT(fdt_property_cell(fdt, "clock-frequency", 1843200));
_FDT(fdt_end_node(fdt));
 }
-#else
-#define serial8250_generate_fdt_node   NULL
 #endif
 
 static struct ioport_operations serial8250_ops = {
.io_in  = serial8250_in,
.io_out = serial8250_out,
-   .generate_fdt_node  = serial8250_generate_fdt_node,
 };
 
-static int serial8250__device_init(struct kvm *kvm, struct serial8250_device 
*dev)
+static int serial8250__device_init(struct kvm *kvm,
+  struct serial8250_device *dev)
 {
int r;
 
+   r = device__register(&g

[PATCH kvmtool v2 01/22] ioport: Remove ioport__setup_arch()

2021-02-24 Thread Andre Przywara
Since x86 had a special need for registering tons of special I/O ports,
we had an ioport__setup_arch() callback, to allow each architecture
to do the same. As it turns out no one uses it beside x86, so we remove
that unnecessary abstraction.

The generic function was registered via a device_base_init() call, so
we just do the same for the x86 specific function only, and can remove
the unneeded ioport__setup_arch().

Signed-off-by: Andre Przywara 
---
 arm/ioport.c | 5 -
 include/kvm/ioport.h | 1 -
 ioport.c | 6 --
 mips/kvm.c   | 5 -
 powerpc/ioport.c | 6 --
 x86/ioport.c | 3 ++-
 6 files changed, 2 insertions(+), 24 deletions(-)

diff --git a/arm/ioport.c b/arm/ioport.c
index 2f0feb9a..24092c9d 100644
--- a/arm/ioport.c
+++ b/arm/ioport.c
@@ -1,11 +1,6 @@
 #include "kvm/ioport.h"
 #include "kvm/irq.h"
 
-int ioport__setup_arch(struct kvm *kvm)
-{
-   return 0;
-}
-
 void ioport__map_irq(u8 *irq)
 {
*irq = irq__alloc_line();
diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
index 039633f7..d0213541 100644
--- a/include/kvm/ioport.h
+++ b/include/kvm/ioport.h
@@ -35,7 +35,6 @@ struct ioport_operations {
enum irq_type));
 };
 
-int ioport__setup_arch(struct kvm *kvm);
 void ioport__map_irq(u8 *irq);
 
 int __must_check ioport__register(struct kvm *kvm, u16 port, struct 
ioport_operations *ops,
diff --git a/ioport.c b/ioport.c
index 844a832d..a6972179 100644
--- a/ioport.c
+++ b/ioport.c
@@ -221,12 +221,6 @@ out:
return !kvm->cfg.ioport_debug;
 }
 
-int ioport__init(struct kvm *kvm)
-{
-   return ioport__setup_arch(kvm);
-}
-dev_base_init(ioport__init);
-
 int ioport__exit(struct kvm *kvm)
 {
ioport__unregister_all();
diff --git a/mips/kvm.c b/mips/kvm.c
index 26355930..e110e5d5 100644
--- a/mips/kvm.c
+++ b/mips/kvm.c
@@ -100,11 +100,6 @@ void kvm__irq_trigger(struct kvm *kvm, int irq)
die_perror("KVM_IRQ_LINE ioctl");
 }
 
-int ioport__setup_arch(struct kvm *kvm)
-{
-   return 0;
-}
-
 bool kvm__arch_cpu_supports_vm(void)
 {
return true;
diff --git a/powerpc/ioport.c b/powerpc/ioport.c
index 0c188b61..a5cff4ee 100644
--- a/powerpc/ioport.c
+++ b/powerpc/ioport.c
@@ -12,12 +12,6 @@
 
 #include 
 
-int ioport__setup_arch(struct kvm *kvm)
-{
-   /* PPC has no legacy ioports to set up */
-   return 0;
-}
-
 void ioport__map_irq(u8 *irq)
 {
 }
diff --git a/x86/ioport.c b/x86/ioport.c
index 7ad7b8f3..a8d2bb1a 100644
--- a/x86/ioport.c
+++ b/x86/ioport.c
@@ -69,7 +69,7 @@ void ioport__map_irq(u8 *irq)
 {
 }
 
-int ioport__setup_arch(struct kvm *kvm)
+static int ioport__setup_arch(struct kvm *kvm)
 {
int r;
 
@@ -150,3 +150,4 @@ int ioport__setup_arch(struct kvm *kvm)
 
return 0;
 }
+dev_base_init(ioport__setup_arch);
-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH kvmtool v2 00/22] Unify I/O port and MMIO trap handling

2021-02-24 Thread Andre Przywara
Compared to v1 this has a few fixes, as suggested by Alex.
There is a new patch 20/22, which cleans up the ARM memory map
definition and adds some chart to make it more obvious what is going on.
For a changelog, see below.

==

At the moment we use two separate code paths to handle exits for
KVM_EXIT_IO (ioport.c) and KVM_EXIT_MMIO (mmio.c), even though they
are semantically very similar. Because the trap handler callback routine
is different, devices need to decide on one conduit or need to provide
different handler functions for both of them.

This is not only unnecessary code duplication, but makes switching
devices from I/O port to MMIO a tedious task, even though there is no
real difference between the two, especially on ARM and PowerPC.

For ARM we aim at providing a flexible memory layout, and also have
trouble with the UART and RTC device overlapping with the PCI I/O area,
so it seems indicated to tackle this once and for all.

The first three patches do some cleanup, to simplify things later.

Patch 04/22 lays the groundwork, by extending mmio.c to be able to also
register I/O port trap handlers, using the same callback prototype as
we use for MMIO.

The next 14 patches then convert devices that use the I/O port
interface over to the new joint interface. This requires to rework
the trap handler routine to adhere to the same prototype as the existing
MMIO handlers. For most devices this is done in two steps: a first to
introduce the reworked handler routine, and a second to switch to the new
joint registration routine. For some devices the first step is trivial,
so it's done in one patch.

Patch 19/22 then retires the old I/O port interface, by removing ioport.c
and friends.
Patch 20/22 uses the opportunity to clean up the memory map description,
also declares a new region (from 16MB on), where the final two patches
switch the UART and the RTC device to. They are now registered
on the MMIO "bus", when running on ARM or arm64. This moves them away
from the first 64KB, so they are not in the PCI I/O area anymore.

Please have a look and comment!

Cheers,
Andre

Changelog v1 .. v2:
- rework memory map definition
- add explicit debug output for debug I/O port
- add explicit check for MMIO coalescing on I/O ports
- drop usage of ioport__{read,write}8() from serial
- drop explicit I/O port cleanup routine (to mimic MMIO operation)
- add comment for IOTRAP_BUS_MASK
- minor cleanups / formatting changes

Andre Przywara (22):
  ioport: Remove ioport__setup_arch()
  hw/serial: Use device abstraction for FDT generator function
  ioport: Retire .generate_fdt_node functionality
  mmio: Extend handling to include ioport emulation
  hw/i8042: Clean up data types
  hw/i8042: Refactor trap handler
  hw/i8042: Switch to new trap handlers
  x86/ioport: Refactor trap handlers
  x86/ioport: Switch to new trap handlers
  hw/rtc: Refactor trap handlers
  hw/rtc: Switch to new trap handler
  hw/vesa: Switch trap handling to use MMIO handler
  hw/serial: Refactor trap handler
  hw/serial: Switch to new trap handlers
  vfio: Refactor ioport trap handler
  vfio: Switch to new ioport trap handlers
  virtio: Switch trap handling to use MMIO handler
  pci: Switch trap handling to use MMIO handler
  Remove ioport specific routines
  arm: Reorganise and document memory map
  hw/serial: ARM/arm64: Use MMIO at higher addresses
  hw/rtc: ARM/arm64: Use MMIO at higher addresses

 Makefile  |   1 -
 arm/include/arm-common/kvm-arch.h |  47 --
 arm/ioport.c  |   5 -
 hw/i8042.c|  94 +---
 hw/rtc.c  |  91 ++--
 hw/serial.c   | 160 
 hw/vesa.c |  19 +--
 include/kvm/i8042.h   |   1 -
 include/kvm/ioport.h  |  32 
 include/kvm/kvm.h |  49 ++-
 ioport.c  | 235 --
 mips/kvm.c|   5 -
 mmio.c|  65 +++--
 pci.c |  82 +++
 powerpc/ioport.c  |   6 -
 vfio/core.c   |  50 ---
 virtio/pci.c  |  46 ++
 x86/ioport.c  | 107 +++---
 18 files changed, 433 insertions(+), 662 deletions(-)
 delete mode 100644 ioport.c

-- 
2.17.5

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH kvmtool 13/21] hw/serial: Refactor trap handler

2021-02-24 Thread Andre Przywara
On Mon, 22 Feb 2021 17:40:36 +
Alexandru Elisei  wrote:

Hi Alex,

> On 2/18/21 2:41 PM, Andre Przywara wrote:
> > On Tue, 16 Feb 2021 14:22:05 +
> > Alexandru Elisei  wrote:
> >  
> >> Hi Andre,
> >>
> >> Patch looks good, nitpicks below.
> >>
> >> On 12/10/20 2:29 PM, Andre Przywara wrote:  
> >>> With the planned retirement of the special ioport emulation code, we
> >>> need to provide an emulation function compatible with the MMIO prototype.
> >>>
> >>> Adjust the trap handler to use that new function, and provide shims to
> >>> implement the old ioport interface, for now.
> >>>
> >>> Signed-off-by: Andre Przywara 
> >>> ---
> >>>  hw/serial.c | 97 +++--
> >>>  1 file changed, 65 insertions(+), 32 deletions(-)
> >>>
> >>> diff --git a/hw/serial.c b/hw/serial.c
> >>> index b0465d99..2907089c 100644
> >>> --- a/hw/serial.c
> >>> +++ b/hw/serial.c
> >>> @@ -242,36 +242,31 @@ void serial8250__inject_sysrq(struct kvm *kvm, char 
> >>> sysrq)
> >>>   sysrq_pending = sysrq;
> >>>  }
> >>>  
> >>> -static bool serial8250_out(struct ioport *ioport, struct kvm_cpu *vcpu, 
> >>> u16 port,
> >>> -void *data, int size)
> >>> +static bool serial8250_out(struct serial8250_device *dev, struct kvm_cpu 
> >>> *vcpu,
> >>> +u16 offset, u8 data)
> >>>  {
> >>> - struct serial8250_device *dev = ioport->priv;
> >>> - u16 offset;
> >>>   bool ret = true;
> >>> - char *addr = data;
> >>>  
> >>>   mutex_lock(>mutex);
> >>>  
> >>> - offset = port - dev->iobase;
> >>> -
> >>>   switch (offset) {
> >>>   case UART_TX:
> >>>   if (dev->lcr & UART_LCR_DLAB) {
> >>> - dev->dll = ioport__read8(data);
> >>> + dev->dll = data;
> >>>   break;
> >>>   }
> >>>  
> >>>   /* Loopback mode */
> >>>   if (dev->mcr & UART_MCR_LOOP) {
> >>>   if (dev->rxcnt < FIFO_LEN) {
> >>> - dev->rxbuf[dev->rxcnt++] = *addr;
> >>> + dev->rxbuf[dev->rxcnt++] = data;
> >>>   dev->lsr |= UART_LSR_DR;
> >>>   }
> >>>   break;
> >>>   }
> >>>  
> >>>   if (dev->txcnt < FIFO_LEN) {
> >>> - dev->txbuf[dev->txcnt++] = *addr;
> >>> + dev->txbuf[dev->txcnt++] = data;
> >>>   dev->lsr &= ~UART_LSR_TEMT;
> >>>   if (dev->txcnt == FIFO_LEN / 2)
> >>>   dev->lsr &= ~UART_LSR_THRE;
> >>> @@ -283,18 +278,18 @@ static bool serial8250_out(struct ioport *ioport, 
> >>> struct kvm_cpu *vcpu, u16 port
> >>>   break;
> >>>   case UART_IER:
> >>>   if (!(dev->lcr & UART_LCR_DLAB))
> >>> - dev->ier = ioport__read8(data) & 0x0f;
> >>> + dev->ier = data & 0x0f;
> >>>   else
> >>> - dev->dlm = ioport__read8(data);
> >>> + dev->dlm = data;
> >>>   break;
> >>>   case UART_FCR:
> >>> - dev->fcr = ioport__read8(data);
> >>> + dev->fcr = data;
> >>>   break;
> >>>   case UART_LCR:
> >>> - dev->lcr = ioport__read8(data);
> >>> + dev->lcr = data;
> >>>   break;
> >>>   case UART_MCR:
> >>> - dev->mcr = ioport__read8(data);
> >>> + dev->mcr = data;
> >>>   break;
> >>>   case UART_LSR:
> >>>   /* Factory test */
> >>> @@ -303,7 +298,7 @@ static bool serial8250_out(struct ioport *ioport, 
> >>> struct kvm_cpu *vcpu, u16 port
> >>>   /* Not used */
> >>>   break;
> >>>   case UART_SCR:
> >>> - dev->scr = ioport__read8(data);
>

Re: [PATCH kvmtool 01/21] ioport: Remove ioport__setup_arch()

2021-02-22 Thread Andre Przywara
On Wed, 17 Feb 2021 16:46:47 +
Andre Przywara  wrote:

> On Thu, 11 Feb 2021 17:32:01 +
> Alexandru Elisei  wrote:
> 
> Hi,
> 
> > On 2/11/21 5:16 PM, Andre Przywara wrote:  
> > > On Wed, 10 Feb 2021 17:44:59 +
> > > Alexandru Elisei  wrote:
> > >
> > > Hi Alex,
> > >
> > >> On 12/10/20 2:28 PM, Andre Przywara wrote:
> > >>> Since x86 had a special need for registering tons of special I/O ports,
> > >>> we had an ioport__setup_arch() callback, to allow each architecture
> > >>> to do the same. As it turns out no one uses it beside x86, so we remove
> > >>> that unnecessary abstraction.
> > >>>
> > >>> The generic function was registered via a device_base_init() call, so
> > >>> we just do the same for the x86 specific function only, and can remove
> > >>> the unneeded ioport__setup_arch().
> > >>>
> > >>> Signed-off-by: Andre Przywara 
> > >>> ---
> > >>>  arm/ioport.c |  5 -
> > >>>  include/kvm/ioport.h |  1 -
> > >>>  ioport.c | 28 
> > >>>  mips/kvm.c   |  5 -
> > >>>  powerpc/ioport.c |  6 --
> > >>>  x86/ioport.c | 25 -
> > >>>  6 files changed, 24 insertions(+), 46 deletions(-)
> > >>>
> > >>> diff --git a/arm/ioport.c b/arm/ioport.c
> > >>> index 2f0feb9a..24092c9d 100644
> > >>> --- a/arm/ioport.c
> > >>> +++ b/arm/ioport.c
> > >>> @@ -1,11 +1,6 @@
> > >>>  #include "kvm/ioport.h"
> > >>>  #include "kvm/irq.h"
> > >>>  
> > >>> -int ioport__setup_arch(struct kvm *kvm)
> > >>> -{
> > >>> -   return 0;
> > >>> -}
> > >>> -
> > >>>  void ioport__map_irq(u8 *irq)
> > >>>  {
> > >>> *irq = irq__alloc_line();
> > >>> diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h
> > >>> index 039633f7..d0213541 100644
> > >>> --- a/include/kvm/ioport.h
> > >>> +++ b/include/kvm/ioport.h
> > >>> @@ -35,7 +35,6 @@ struct ioport_operations {
> > >>> enum 
> > >>> irq_type));
> > >>>  };
> > >>>  
> > >>> -int ioport__setup_arch(struct kvm *kvm);
> > >>>  void ioport__map_irq(u8 *irq);
> > >>>  
> > >>>  int __must_check ioport__register(struct kvm *kvm, u16 port, struct 
> > >>> ioport_operations *ops,
> > >>> diff --git a/ioport.c b/ioport.c
> > >>> index 844a832d..667e8386 100644
> > >>> --- a/ioport.c
> > >>> +++ b/ioport.c
> > >>> @@ -158,21 +158,6 @@ int ioport__unregister(struct kvm *kvm, u16 port)
> > >>> return 0;
> > >>>  }
> > >>>  
> > >>> -static void ioport__unregister_all(void)
> > >>> -{
> > >>> -   struct ioport *entry;
> > >>> -   struct rb_node *rb;
> > >>> -   struct rb_int_node *rb_node;
> > >>> -
> > >>> -   rb = rb_first(_tree);
> > >>> -   while (rb) {
> > >>> -   rb_node = rb_int(rb);
> > >>> -   entry = ioport_node(rb_node);
> > >>> -   ioport_unregister(_tree, entry);
> > >>> -   rb = rb_first(_tree);
> > >>> -   }
> > >>> -}  
> > >> I get the impression this is a rebasing artifact. The commit message 
> > >> doesn't
> > >> mention anything about removing ioport__exit() -> 
> > >> ioport__unregister_all(), and as
> > >> far as I can tell it's still needed because there are places other than
> > >> ioport__setup_arch() from where ioport__register() is called.
> > > I agree that the commit message is a bit thin on this fact, but the
> > > functionality of ioport__unregister_all() is now in
> > > x86/ioport.c:ioport__remove_arch(). I think removing ioport__init()
> > > without removing ioport__exit() as well would look very weird, if not
> > > hackish.
> > 
> > Not necessarily. ioport__unregister_all() removes the ioports added by
&g

Re: [PATCH kvmtool 21/21] hw/rtc: ARM/arm64: Use MMIO at higher addresses

2021-02-18 Thread Andre Przywara
On Thu, 18 Feb 2021 13:33:15 +
Alexandru Elisei  wrote:

> Hi Andre,
> 
> On 12/10/20 2:29 PM, Andre Przywara wrote:
> > Using the RTC device at its legacy I/O address as set by IBM in 1981
> > was a kludge we used for simplicity on ARM platforms as well.
> > However this imposes problems due to their missing alignment and overlap
> > with the PCI I/O address space.
> >
> > Now that we can switch a device easily between using ioports and
> > MMIO, let's move the RTC out of the first 4K of memory on ARM platforms.
> >
> > That should be transparent for well behaved guests, since the change is
> > naturally reflected in the device tree.
> >
> > Signed-off-by: Andre Przywara 
> > ---
> >  hw/rtc.c | 24 
> >  1 file changed, 16 insertions(+), 8 deletions(-)
> >
> > diff --git a/hw/rtc.c b/hw/rtc.c
> > index ee4c9102..bdb88f0f 100644
> > --- a/hw/rtc.c
> > +++ b/hw/rtc.c
> > @@ -5,6 +5,15 @@
> >  
> >  #include 
> >  
> > +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
> > +#define RTC_BUS_TYPE   DEVICE_BUS_MMIO
> > +#define RTC_BASE_ADDRESS   0x101  
> 
> This looks correct, the base address is the serial base address + 64k, so they
> don't overlap, and it doesn't overlap with the flash memory either. Same 
> comment
> as for the serial, I think the reason for choosing this address should be
> mentioned, and the region should be put in the arch memory layout file. Other 
> than
> that, the patch looks good.

Yep, will do!

Thanks,
Andre

> 
> > +#else
> > +/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
> > +#define RTC_BUS_TYPE   DEVICE_BUS_IOPORT
> > +#define RTC_BASE_ADDRESS   0x70
> > +#endif
> > +
> >  /*
> >   * MC146818 RTC registers
> >   */
> > @@ -49,7 +58,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, 
> > u8 *data,
> > time_t ti;
> >  
> > if (is_write) {
> > -   if (addr == 0x70) { /* index register */
> > +   if (addr == RTC_BASE_ADDRESS) { /* index register */
> > u8 value = ioport__read8(data);
> >  
> > vcpu->kvm->nmi_disabled = value & (1UL << 7);
> > @@ -70,7 +79,7 @@ static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, 
> > u8 *data,
> > return;
> > }
> >  
> > -   if (addr == 0x70)
> > +   if (addr == RTC_BASE_ADDRESS)   /* index register is write-only */
> > return;
> >  
> > time();
> > @@ -127,7 +136,7 @@ static void generate_rtc_fdt_node(void *fdt,
> > u8 irq,
> > enum irq_type))
> >  {
> > -   u64 reg_prop[2] = { cpu_to_fdt64(0x70), cpu_to_fdt64(2) };
> > +   u64 reg_prop[2] = { cpu_to_fdt64(RTC_BASE_ADDRESS), cpu_to_fdt64(2) };
> >  
> > _FDT(fdt_begin_node(fdt, "rtc"));
> > _FDT(fdt_property_string(fdt, "compatible", "motorola,mc146818"));
> > @@ -139,7 +148,7 @@ static void generate_rtc_fdt_node(void *fdt,
> >  #endif
> >  
> >  struct device_header rtc_dev_hdr = {
> > -   .bus_type = DEVICE_BUS_IOPORT,
> > +   .bus_type = RTC_BUS_TYPE,
> > .data = generate_rtc_fdt_node,
> >  };
> >  
> > @@ -151,8 +160,8 @@ int rtc__init(struct kvm *kvm)
> > if (r < 0)
> > return r;
> >  
> > -   /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
> > -   r = kvm__register_pio(kvm, 0x0070, 2, cmos_ram_io, NULL);
> > +   r = kvm__register_iotrap(kvm, RTC_BASE_ADDRESS, 2, cmos_ram_io, NULL,
> > +RTC_BUS_TYPE);
> > if (r < 0)
> > goto out_device;
> >  
> > @@ -170,8 +179,7 @@ dev_init(rtc__init);
> >  
> >  int rtc__exit(struct kvm *kvm)
> >  {
> > -   /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
> > -   kvm__deregister_pio(kvm, 0x0070);
> > +   kvm__deregister_iotrap(kvm, RTC_BASE_ADDRESS, RTC_BUS_TYPE);
> >  
> > return 0;
> >  }  

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


  1   2   3   4   5   6   7   8   9   10   >