Skip to content

Commit

Permalink
Merge pull request #290 from lixianglai/linux-6.6.y
Browse files Browse the repository at this point in the history
add loongarch kvm support for Linux 6.6.y
  • Loading branch information
Avenger-285714 authored Jun 21, 2024
2 parents 108aebd + eb01ecf commit b95e42b
Show file tree
Hide file tree
Showing 46 changed files with 6,582 additions and 120 deletions.
70 changes: 61 additions & 9 deletions Documentation/virt/kvm/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,13 @@ Reads the general purpose registers from the vcpu.
__u64 pc;
};

/* LoongArch */
struct kvm_regs {
/* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
unsigned long gpr[32];
unsigned long pc;
};


4.12 KVM_SET_REGS
-----------------
Expand Down Expand Up @@ -506,7 +513,7 @@ translation mode.
------------------

:Capability: basic
:Architectures: x86, ppc, mips, riscv
:Architectures: x86, ppc, mips, riscv, loongarch
:Type: vcpu ioctl
:Parameters: struct kvm_interrupt (in)
:Returns: 0 on success, negative on failure.
Expand Down Expand Up @@ -592,6 +599,14 @@ b) KVM_INTERRUPT_UNSET

This is an asynchronous vcpu ioctl and can be invoked from any thread.

LOONGARCH:
^^^^^^^^^^

Queues an external interrupt to be injected into the virtual CPU. A negative
interrupt number dequeues the interrupt.

This is an asynchronous vcpu ioctl and can be invoked from any thread.


4.17 KVM_DEBUG_GUEST
--------------------
Expand Down Expand Up @@ -737,7 +752,7 @@ signal mask.
----------------

:Capability: basic
:Architectures: x86
:Architectures: x86, loongarch
:Type: vcpu ioctl
:Parameters: struct kvm_fpu (out)
:Returns: 0 on success, -1 on error
Expand All @@ -746,7 +761,7 @@ Reads the floating point state from the vcpu.

::

/* for KVM_GET_FPU and KVM_SET_FPU */
/* x86: for KVM_GET_FPU and KVM_SET_FPU */
struct kvm_fpu {
__u8 fpr[8][16];
__u16 fcw;
Expand All @@ -761,12 +776,21 @@ Reads the floating point state from the vcpu.
__u32 pad2;
};

/* LoongArch: for KVM_GET_FPU and KVM_SET_FPU */
struct kvm_fpu {
__u32 fcsr;
__u64 fcc;
struct kvm_fpureg {
__u64 val64[4];
}fpr[32];
};


4.23 KVM_SET_FPU
----------------

:Capability: basic
:Architectures: x86
:Architectures: x86, loongarch
:Type: vcpu ioctl
:Parameters: struct kvm_fpu (in)
:Returns: 0 on success, -1 on error
Expand All @@ -775,7 +799,7 @@ Writes the floating point state to the vcpu.

::

/* for KVM_GET_FPU and KVM_SET_FPU */
/* x86: for KVM_GET_FPU and KVM_SET_FPU */
struct kvm_fpu {
__u8 fpr[8][16];
__u16 fcw;
Expand All @@ -790,6 +814,15 @@ Writes the floating point state to the vcpu.
__u32 pad2;
};

/* LoongArch: for KVM_GET_FPU and KVM_SET_FPU */
struct kvm_fpu {
__u32 fcsr;
__u64 fcc;
struct kvm_fpureg {
__u64 val64[4];
}fpr[32];
};


4.24 KVM_CREATE_IRQCHIP
-----------------------
Expand Down Expand Up @@ -1387,7 +1420,7 @@ documentation when it pops into existence).
-------------------

:Capability: KVM_CAP_ENABLE_CAP
:Architectures: mips, ppc, s390, x86
:Architectures: mips, ppc, s390, x86, loongarch
:Type: vcpu ioctl
:Parameters: struct kvm_enable_cap (in)
:Returns: 0 on success; -1 on error
Expand Down Expand Up @@ -1442,7 +1475,7 @@ for vm-wide capabilities.
---------------------

:Capability: KVM_CAP_MP_STATE
:Architectures: x86, s390, arm64, riscv
:Architectures: x86, s390, arm64, riscv, loongarch
:Type: vcpu ioctl
:Parameters: struct kvm_mp_state (out)
:Returns: 0 on success; -1 on error
Expand All @@ -1460,7 +1493,7 @@ Possible values are:

========================== ===============================================
KVM_MP_STATE_RUNNABLE the vcpu is currently running
[x86,arm64,riscv]
[x86,arm64,riscv,loongarch]
KVM_MP_STATE_UNINITIALIZED the vcpu is an application processor (AP)
which has not yet received an INIT signal [x86]
KVM_MP_STATE_INIT_RECEIVED the vcpu has received an INIT signal, and is
Expand Down Expand Up @@ -1516,11 +1549,14 @@ For riscv:
The only states that are valid are KVM_MP_STATE_STOPPED and
KVM_MP_STATE_RUNNABLE which reflect if the vcpu is paused or not.

On LoongArch, only the KVM_MP_STATE_RUNNABLE state is used to reflect
whether the vcpu is runnable.

4.39 KVM_SET_MP_STATE
---------------------

:Capability: KVM_CAP_MP_STATE
:Architectures: x86, s390, arm64, riscv
:Architectures: x86, s390, arm64, riscv, loongarch
:Type: vcpu ioctl
:Parameters: struct kvm_mp_state (in)
:Returns: 0 on success; -1 on error
Expand All @@ -1538,6 +1574,9 @@ For arm64/riscv:
The only states that are valid are KVM_MP_STATE_STOPPED and
KVM_MP_STATE_RUNNABLE which reflect if the vcpu should be paused or not.

On LoongArch, only the KVM_MP_STATE_RUNNABLE state is used to reflect
whether the vcpu is runnable.

4.40 KVM_SET_IDENTITY_MAP_ADDR
------------------------------

Expand Down Expand Up @@ -2841,6 +2880,19 @@ Following are the RISC-V D-extension registers:
0x8020 0000 0600 0020 fcsr Floating point control and status register
======================= ========= =============================================

LoongArch registers are mapped using the lower 32 bits. The upper 16 bits of
that is the register group type.

LoongArch csr registers are used to control guest cpu or get status of guest
cpu, and they have the following id bit patterns::

0x9030 0000 0001 00 <reg:5> <sel:3> (64-bit)

LoongArch KVM control registers are used to implement some new defined functions
such as set vcpu counter or reset vcpu, and they have the following id bit patterns::

0x9030 0000 0002 <reg:16>


4.69 KVM_GET_ONE_REG
--------------------
Expand Down
1 change: 1 addition & 0 deletions Documentation/virt/kvm/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ KVM
s390/index
ppc-pv
x86/index
loongarch/index

locking
vcpu-requests
Expand Down
79 changes: 79 additions & 0 deletions Documentation/virt/kvm/loongarch/hypercalls.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
.. SPDX-License-Identifier: GPL-2.0
===================================
The LoongArch paravirtual interface
===================================

KVM hypercalls use the HVCL instruction with code 0x100, and the hypercall
number is put in a0 and up to five arguments may be placed in a1-a5, the
return value is placed in v0 (alias with a0).

The code for that interface can be found in arch/loongarch/kvm/*

Querying for existence
======================

To find out if we're running on KVM or not, cpucfg can be used with index
CPUCFG_KVM_BASE (0x40000000), cpucfg range between 0x40000000 - 0x400000FF
is marked as a specially reserved range. All existing and future processors
will not implement any features in this range.

When Linux is running on KVM, cpucfg with index CPUCFG_KVM_BASE (0x40000000)
returns magic string "KVM\0"

Once you determined you're running under a PV capable KVM, you can now use
hypercalls as described below.

KVM hypercall ABI
=================

Hypercall ABI on KVM is simple, only one scratch register a0 (v0) and at most
five generic registers used as input parameter. FP register and vector register
is not used for input register and should not be modified during hypercall.
Hypercall function can be inlined since there is only one scratch register.

The parameters are as follows:

======== ================ ================
Register IN OUT
======== ================ ================
a0 function number Return code
a1 1st parameter -
a2 2nd parameter -
a3 3rd parameter -
a4 4th parameter -
a5 5th parameter -
======== ================ ================

Return codes can be as follows:

==== =========================
Code Meaning
==== =========================
0 Success
-1 Hypercall not implemented
-2 Hypercall parameter error
==== =========================

KVM Hypercalls Documentation
============================

The template for each hypercall is:
1. Hypercall name
2. Purpose

1. KVM_HCALL_FUNC_PV_IPI
------------------------

:Purpose: Send IPIs to multiple vCPUs.

- a0: KVM_HCALL_FUNC_PV_IPI
- a1: lower part of the bitmap of destination physical CPUIDs
- a2: higher part of the bitmap of destination physical CPUIDs
- a3: the lowest physical CPUID in bitmap

The hypercall lets a guest send multicast IPIs, with at most 128
destinations per hypercall. The destinations are represented by a bitmap
contained in the first two arguments (a1 and a2). Bit 0 of a1 corresponds
to the physical CPUID in the third argument (a3), bit 1 corresponds to the
physical ID a3+1, and so on.
10 changes: 10 additions & 0 deletions Documentation/virt/kvm/loongarch/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.. SPDX-License-Identifier: GPL-2.0
=========================
KVM for LoongArch systems
=========================

.. toctree::
:maxdepth: 2

hypercalls.rst
12 changes: 12 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -11527,6 +11527,18 @@ F: include/kvm/arm_*
F: tools/testing/selftests/kvm/*/aarch64/
F: tools/testing/selftests/kvm/aarch64/

KERNEL VIRTUAL MACHINE FOR LOONGARCH (KVM/LoongArch)
M: Tianrui Zhao <[email protected]>
M: Bibo Mao <[email protected]>
M: Huacai Chen <[email protected]>
L: [email protected]
L: [email protected]
S: Maintained
T: git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
F: arch/loongarch/include/asm/kvm*
F: arch/loongarch/include/uapi/asm/kvm*
F: arch/loongarch/kvm/

KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
M: Huacai Chen <[email protected]>
L: [email protected]
Expand Down
2 changes: 2 additions & 0 deletions arch/loongarch/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ obj-y += mm/
obj-y += net/
obj-y += vdso/

obj-$(CONFIG_KVM) += kvm/

# for cleaning
subdir- += boot
15 changes: 15 additions & 0 deletions arch/loongarch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ config LOONGARCH
select HAVE_KPROBES
select HAVE_KPROBES_ON_FTRACE
select HAVE_KRETPROBES
select HAVE_KVM
select HAVE_MOD_ARCH_SPECIFIC
select HAVE_NMI
select HAVE_PCI
Expand Down Expand Up @@ -266,6 +267,9 @@ config AS_HAS_LASX_EXTENSION
config AS_HAS_LBT_EXTENSION
def_bool $(as-instr,movscr2gr \$a0$(comma)\$scr0)

config AS_HAS_LVZ_EXTENSION
def_bool $(as-instr,hvcl 0)

menu "Kernel type and options"

source "kernel/Kconfig.hz"
Expand Down Expand Up @@ -562,6 +566,15 @@ config CPU_HAS_PREFETCH
bool
default y

config PARAVIRT
bool "Enable paravirtualization code"
depends on AS_HAS_LVZ_EXTENSION
help
This changes the kernel so it can modify itself when it is run
under a hypervisor, potentially improving performance significantly
over full virtualization. However, when run without a hypervisor
the kernel is theoretically slower and slightly larger.

config ARCH_SUPPORTS_KEXEC
def_bool y

Expand Down Expand Up @@ -659,3 +672,5 @@ source "kernel/power/Kconfig"
source "drivers/acpi/Kconfig"

endmenu

source "arch/loongarch/kvm/Kconfig"
2 changes: 2 additions & 0 deletions arch/loongarch/configs/loongson3_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,8 @@ CONFIG_ISCSI_IBFT=m
CONFIG_EFI_ZBOOT=y
CONFIG_EFI_CAPSULE_LOADER=m
CONFIG_EFI_TEST=m
CONFIG_VIRTUALIZATION=y
CONFIG_KVM=m
CONFIG_MTD=m
CONFIG_MTD_BLOCK=m
CONFIG_MTD_CFI=m
Expand Down
1 change: 0 additions & 1 deletion arch/loongarch/include/asm/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,3 @@ generic-y += poll.h
generic-y += param.h
generic-y += posix_types.h
generic-y += resource.h
generic-y += kvm_para.h
5 changes: 5 additions & 0 deletions arch/loongarch/include/asm/hardirq.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@
extern void ack_bad_irq(unsigned int irq);
#define ack_bad_irq ack_bad_irq

enum ipi_msg_type {
IPI_RESCHEDULE,
IPI_CALL_FUNCTION,
};
#define NR_IPI 2

typedef struct {
unsigned int ipi_irqs[NR_IPI];
unsigned int __softirq_pending;
atomic_t message ____cacheline_aligned_in_smp;
} ____cacheline_aligned irq_cpustat_t;

DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
Expand Down
Loading

0 comments on commit b95e42b

Please sign in to comment.