summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS2
-rw-r--r--bsd-user/main.c2
-rw-r--r--docs/devel/s390-dasd-ipl.txt133
-rw-r--r--docs/nvdimm.txt22
-rw-r--r--exec.c54
-rw-r--r--hw/arm/virt.c9
-rw-r--r--hw/core/machine.c3
-rw-r--r--hw/i386/amd_iommu.c2
-rw-r--r--hw/i386/intel_iommu.c2
-rw-r--r--hw/i386/pc.c3
-rw-r--r--hw/i386/pc_piix.c15
-rw-r--r--hw/i386/pc_q35.c13
-rw-r--r--hw/pci/pci.c2
-rw-r--r--hw/ppc/Makefile.objs2
-rw-r--r--hw/ppc/prep.c1
-rw-r--r--hw/ppc/spapr.c104
-rw-r--r--hw/ppc/spapr_caps.c4
-rw-r--r--hw/ppc/spapr_hcall.c24
-rw-r--r--hw/ppc/spapr_irq.c44
-rw-r--r--hw/ppc/spapr_pci.c48
-rw-r--r--hw/ppc/spapr_pci_nvlink2.c450
-rw-r--r--hw/ppc/spapr_rtas.c2
-rw-r--r--hw/s390x/ipl.c61
-rw-r--r--hw/s390x/s390-ccw.c9
-rw-r--r--hw/s390x/s390-virtio-ccw.c26
-rw-r--r--hw/vfio/ccw.c6
-rw-r--r--hw/vfio/pci-quirks.c131
-rw-r--r--hw/vfio/pci.c14
-rw-r--r--hw/vfio/pci.h2
-rw-r--r--hw/vfio/spapr.c2
-rw-r--r--hw/vfio/trace-events4
-rw-r--r--include/exec/ram_addr.h3
-rw-r--r--include/hw/boards.h4
-rw-r--r--include/hw/i386/pc.h3
-rw-r--r--include/hw/pci-host/spapr.h45
-rw-r--r--include/hw/pci/pci.h4
-rw-r--r--include/hw/ppc/spapr.h11
-rw-r--r--include/hw/s390x/s390-ccw.h1
-rw-r--r--include/hw/s390x/vfio-ccw.h28
-rw-r--r--include/qemu/mmap-alloc.h21
-rw-r--r--include/qom/cpu.h6
-rw-r--r--linux-headers/asm-arm/mman.h4
-rw-r--r--linux-headers/asm-arm64/mman.h1
-rw-r--r--linux-headers/asm-generic/hugetlb_encode.h36
-rw-r--r--linux-headers/asm-generic/mman-common.h77
-rw-r--r--linux-headers/asm-generic/mman.h24
-rw-r--r--linux-headers/asm-mips/mman.h108
-rw-r--r--linux-headers/asm-powerpc/mman.h39
-rw-r--r--linux-headers/asm-s390/mman.h1
-rw-r--r--linux-headers/asm-x86/mman.h31
-rw-r--r--linux-headers/linux/mman.h38
-rw-r--r--linux-user/main.c2
-rw-r--r--pc-bios/s390-ccw.imgbin34568 -> 42608 bytes
-rw-r--r--pc-bios/s390-ccw/Makefile2
-rw-r--r--pc-bios/s390-ccw/cio.c423
-rw-r--r--pc-bios/s390-ccw/cio.h270
-rw-r--r--pc-bios/s390-ccw/dasd-ipl.c235
-rw-r--r--pc-bios/s390-ccw/dasd-ipl.h16
-rw-r--r--pc-bios/s390-ccw/helper.h31
-rw-r--r--pc-bios/s390-ccw/libc.h11
-rw-r--r--pc-bios/s390-ccw/main.c190
-rw-r--r--pc-bios/s390-ccw/netboot.mak2
-rw-r--r--pc-bios/s390-ccw/netmain.c2
-rw-r--r--pc-bios/s390-ccw/s390-arch.h103
-rw-r--r--pc-bios/s390-ccw/s390-ccw.h10
-rw-r--r--pc-bios/s390-ccw/start.S29
-rw-r--r--pc-bios/s390-ccw/virtio.c81
-rw-r--r--pc-bios/s390-netboot.imgbin54944 -> 67232 bytes
-rw-r--r--qemu-options.hx5
-rwxr-xr-xscripts/update-linux-headers.sh6
-rw-r--r--target/i386/cpu.c54
-rw-r--r--target/i386/cpu.h2
-rw-r--r--target/ppc/cpu-models.c2
-rw-r--r--target/ppc/cpu-models.h3
-rw-r--r--target/ppc/cpu.h241
-rw-r--r--target/ppc/dfp_helper.c14
-rw-r--r--target/ppc/excp_helper.c87
-rw-r--r--target/ppc/fpu_helper.c134
-rw-r--r--target/ppc/gdbstub.c34
-rw-r--r--target/ppc/helper_regs.h10
-rw-r--r--target/ppc/int_helper.c70
-rw-r--r--target/ppc/kvm.c246
-rw-r--r--target/ppc/kvm_ppc.h3
-rw-r--r--target/ppc/machine.c106
-rw-r--r--target/ppc/mem_helper.c33
-rw-r--r--target/ppc/mfrom_table.inc.c3
-rw-r--r--target/ppc/mfrom_table_gen.c8
-rw-r--r--target/ppc/misc_helper.c9
-rw-r--r--target/ppc/mmu-hash32.c59
-rw-r--r--target/ppc/mmu-hash64.c136
-rw-r--r--target/ppc/mmu-hash64.h2
-rw-r--r--target/ppc/mmu-radix64.c16
-rw-r--r--target/ppc/mmu_helper.c144
-rw-r--r--target/ppc/monitor.c11
-rw-r--r--target/ppc/trace-events29
-rw-r--r--target/ppc/translate.c504
-rw-r--r--target/ppc/translate/fp-impl.inc.c52
-rw-r--r--target/ppc/translate/spe-impl.inc.c14
-rw-r--r--target/ppc/translate/vmx-impl.inc.c26
-rw-r--r--target/ppc/translate/vsx-impl.inc.c15
-rw-r--r--target/ppc/translate_init.inc.c243
-rw-r--r--target/s390x/cpu.c7
-rw-r--r--target/s390x/cpu.h1
-rw-r--r--target/s390x/kvm-stub.c4
-rw-r--r--target/s390x/kvm.c35
-rw-r--r--target/s390x/kvm_s390x.h1
-rw-r--r--tests/acceptance/empty_cpu_model.py19
-rw-r--r--tests/boot-serial-test.c2
-rw-r--r--util/mmap-alloc.c47
-rw-r--r--util/oslib-posix.c2
-rw-r--r--vl.c87
111 files changed, 4335 insertions, 1279 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 23db6f8408..dabbfccf9c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1181,6 +1181,7 @@ S: Supported
F: hw/s390x/ipl.*
F: pc-bios/s390-ccw/
F: pc-bios/s390-ccw.img
+F: docs/devel/s390-dasd-ipl.txt
T: git https://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org
@@ -1445,6 +1446,7 @@ S: Supported
F: hw/vfio/ccw.c
F: hw/s390x/s390-ccw.c
F: include/hw/s390x/s390-ccw.h
+F: include/hw/s390x/vfio-ccw.h
T: git https://github.com/cohuck/qemu.git s390-next
L: qemu-s390x@nongnu.org
diff --git a/bsd-user/main.c b/bsd-user/main.c
index a8c807e8df..6192e9d91e 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -905,7 +905,7 @@ int main(int argc, char **argv)
/* init tcg before creating CPUs and to get qemu_host_page_size */
tcg_exec_init(0);
- cpu_type = parse_cpu_model(cpu_model);
+ cpu_type = parse_cpu_option(cpu_model);
cpu = cpu_create(cpu_type);
env = cpu->env_ptr;
#if defined(TARGET_SPARC) || defined(TARGET_PPC)
diff --git a/docs/devel/s390-dasd-ipl.txt b/docs/devel/s390-dasd-ipl.txt
new file mode 100644
index 0000000000..9107e048e4
--- /dev/null
+++ b/docs/devel/s390-dasd-ipl.txt
@@ -0,0 +1,133 @@
+*****************************
+***** s390 hardware IPL *****
+*****************************
+
+The s390 hardware IPL process consists of the following steps.
+
+1. A READ IPL ccw is constructed in memory location 0x0.
+ This ccw, by definition, reads the IPL1 record which is located on the disk
+ at cylinder 0 track 0 record 1. Note that the chain flag is on in this ccw
+ so when it is complete another ccw will be fetched and executed from memory
+ location 0x08.
+
+2. Execute the Read IPL ccw at 0x00, thereby reading IPL1 data into 0x00.
+ IPL1 data is 24 bytes in length and consists of the following pieces of
+ information: [psw][read ccw][tic ccw]. When the machine executes the Read
+ IPL ccw it read the 24-bytes of IPL1 to be read into memory starting at
+ location 0x0. Then the ccw program at 0x08 which consists of a read
+ ccw and a tic ccw is automatically executed because of the chain flag from
+ the original READ IPL ccw. The read ccw will read the IPL2 data into memory
+ and the TIC (Transfer In Channel) will transfer control to the channel
+ program contained in the IPL2 data. The TIC channel command is the
+ equivalent of a branch/jump/goto instruction for channel programs.
+ NOTE: The ccws in IPL1 are defined by the architecture to be format 0.
+
+3. Execute IPL2.
+ The TIC ccw instruction at the end of the IPL1 channel program will begin
+ the execution of the IPL2 channel program. IPL2 is stage-2 of the boot
+ process and will contain a larger channel program than IPL1. The point of
+ IPL2 is to find and load either the operating system or a small program that
+ loads the operating system from disk. At the end of this step all or some of
+ the real operating system is loaded into memory and we are ready to hand
+ control over to the guest operating system. At this point the guest
+ operating system is entirely responsible for loading any more data it might
+ need to function. NOTE: The IPL2 channel program might read data into memory
+ location 0 thereby overwriting the IPL1 psw and channel program. This is ok
+ as long as the data placed in location 0 contains a psw whose instruction
+ address points to the guest operating system code to execute at the end of
+ the IPL/boot process.
+ NOTE: The ccws in IPL2 are defined by the architecture to be format 0.
+
+4. Start executing the guest operating system.
+ The psw that was loaded into memory location 0 as part of the ipl process
+ should contain the needed flags for the operating system we have loaded. The
+ psw's instruction address will point to the location in memory where we want
+ to start executing the operating system. This psw is loaded (via LPSW
+ instruction) causing control to be passed to the operating system code.
+
+In a non-virtualized environment this process, handled entirely by the hardware,
+is kicked off by the user initiating a "Load" procedure from the hardware
+management console. This "Load" procedure crafts a special "Read IPL" ccw in
+memory location 0x0 that reads IPL1. It then executes this ccw thereby kicking
+off the reading of IPL1 data. Since the channel program from IPL1 will be
+written immediately after the special "Read IPL" ccw, the IPL1 channel program
+will be executed immediately (the special read ccw has the chaining bit turned
+on). The TIC at the end of the IPL1 channel program will cause the IPL2 channel
+program to be executed automatically. After this sequence completes the "Load"
+procedure then loads the psw from 0x0.
+
+**********************************************************
+***** How this all pertains to QEMU (and the kernel) *****
+**********************************************************
+
+In theory we should merely have to do the following to IPL/boot a guest
+operating system from a DASD device:
+
+1. Place a "Read IPL" ccw into memory location 0x0 with chaining bit on.
+2. Execute channel program at 0x0.
+3. LPSW 0x0.
+
+However, our emulation of the machine's channel program logic within the kernel
+is missing one key feature that is required for this process to work:
+non-prefetch of ccw data.
+
+When we start a channel program we pass the channel subsystem parameters via an
+ORB (Operation Request Block). One of those parameters is a prefetch bit. If the
+bit is on then the vfio-ccw kernel driver is allowed to read the entire channel
+program from guest memory before it starts executing it. This means that any
+channel commands that read additional channel commands will not work as expected
+because the newly read commands will only exist in guest memory and NOT within
+the kernel's channel subsystem memory. The kernel vfio-ccw driver currently
+requires this bit to be on for all channel programs. This is a problem because
+the IPL process consists of transferring control from the "Read IPL" ccw
+immediately to the IPL1 channel program that was read by "Read IPL".
+
+Not being able to turn off prefetch will also prevent the TIC at the end of the
+IPL1 channel program from transferring control to the IPL2 channel program.
+
+Lastly, in some cases (the zipl bootloader for example) the IPL2 program also
+transfers control to another channel program segment immediately after reading
+it from the disk. So we need to be able to handle this case.
+
+**************************
+***** What QEMU does *****
+**************************
+
+Since we are forced to live with prefetch we cannot use the very simple IPL
+procedure we defined in the preceding section. So we compensate by doing the
+following.
+
+1. Place "Read IPL" ccw into memory location 0x0, but turn off chaining bit.
+2. Execute "Read IPL" at 0x0.
+
+ So now IPL1's psw is at 0x0 and IPL1's channel program is at 0x08.
+
+4. Write a custom channel program that will seek to the IPL2 record and then
+ execute the READ and TIC ccws from IPL1. Normally the seek is not required
+ because after reading the IPL1 record the disk is automatically positioned
+ to read the very next record which will be IPL2. But since we are not reading
+ both IPL1 and IPL2 as part of the same channel program we must manually set
+ the position.
+
+5. Grab the target address of the TIC instruction from the IPL1 channel program.
+ This address is where the IPL2 channel program starts.
+
+ Now IPL2 is loaded into memory somewhere, and we know the address.
+
+6. Execute the IPL2 channel program at the address obtained in step #5.
+
+ Because this channel program can be dynamic, we must use a special algorithm
+ that detects a READ immediately followed by a TIC and breaks the ccw chain
+ by turning off the chain bit in the READ ccw. When control is returned from
+ the kernel/hardware to the QEMU bios code we immediately issue another start
+ subchannel to execute the remaining TIC instruction. This causes the entire
+ channel program (starting from the TIC) and all needed data to be refetched
+ thereby stepping around the limitation that would otherwise prevent this
+ channel program from executing properly.
+
+ Now the operating system code is loaded somewhere in guest memory and the psw
+ in memory location 0x0 will point to entry code for the guest operating
+ system.
+
+7. LPSW 0x0.
+ LPSW transfers control to the guest operating system and we're done.
diff --git a/docs/nvdimm.txt b/docs/nvdimm.txt
index 7231c2d78f..b531cacd35 100644
--- a/docs/nvdimm.txt
+++ b/docs/nvdimm.txt
@@ -144,9 +144,25 @@ Guest Data Persistence
----------------------
Though QEMU supports multiple types of vNVDIMM backends on Linux,
-currently the only one that can guarantee the guest write persistence
-is the device DAX on the real NVDIMM device (e.g., /dev/dax0.0), to
-which all guest access do not involve any host-side kernel cache.
+the only backend that can guarantee the guest write persistence is:
+
+A. DAX device (e.g., /dev/dax0.0, ) or
+B. DAX file(mounted with dax option)
+
+When using B (A file supporting direct mapping of persistent memory)
+as a backend, write persistence is guaranteed if the host kernel has
+support for the MAP_SYNC flag in the mmap system call (available
+since Linux 4.15 and on certain distro kernels) and additionally
+both 'pmem' and 'share' flags are set to 'on' on the backend.
+
+If these conditions are not satisfied i.e. if either 'pmem' or 'share'
+are not set, if the backend file does not support DAX or if MAP_SYNC
+is not supported by the host kernel, write persistence is not
+guaranteed after a system crash. For compatibility reasons, these
+conditions are ignored if not satisfied. Currently, no way is
+provided to test for them.
+For more details, please reference mmap(2) man page:
+http://man7.org/linux/man-pages/man2/mmap.2.html.
When using other types of backends, it's suggested to set 'unarmed'
option of '-device nvdimm' to 'on', which sets the unarmed flag of the
diff --git a/exec.c b/exec.c
index 2646207661..4e734770c2 100644
--- a/exec.c
+++ b/exec.c
@@ -983,14 +983,18 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
#endif
}
-const char *parse_cpu_model(const char *cpu_model)
+const char *parse_cpu_option(const char *cpu_option)
{
ObjectClass *oc;
CPUClass *cc;
gchar **model_pieces;
const char *cpu_type;
- model_pieces = g_strsplit(cpu_model, ",", 2);
+ model_pieces = g_strsplit(cpu_option, ",", 2);
+ if (!model_pieces[0]) {
+ error_report("-cpu option cannot be empty");
+ exit(1);
+ }
oc = cpu_class_by_name(CPU_RESOLVING_TYPE, model_pieces[0]);
if (oc == NULL) {
@@ -1688,7 +1692,7 @@ void ram_block_dump(Monitor *mon)
* when we actually open and map them. Iterate over the file
* descriptors instead, and use qemu_fd_getpagesize().
*/
-static int find_max_supported_pagesize(Object *obj, void *opaque)
+static int find_min_backend_pagesize(Object *obj, void *opaque)
{
long *hpsize_min = opaque;
@@ -1704,7 +1708,27 @@ static int find_max_supported_pagesize(Object *obj, void *opaque)
return 0;
}
-long qemu_getrampagesize(void)
+static int find_max_backend_pagesize(Object *obj, void *opaque)
+{
+ long *hpsize_max = opaque;
+
+ if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ long hpsize = host_memory_backend_pagesize(backend);
+
+ if (host_memory_backend_is_mapped(backend) && (hpsize > *hpsize_max)) {
+ *hpsize_max = hpsize;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * TODO: We assume right now that all mapped host memory backends are
+ * used as RAM, however some might be used for different purposes.
+ */
+long qemu_minrampagesize(void)
{
long hpsize = LONG_MAX;
long mainrampagesize;
@@ -1724,7 +1748,7 @@ long qemu_getrampagesize(void)
*/
memdev_root = object_resolve_path("/objects", NULL);
if (memdev_root) {
- object_child_foreach(memdev_root, find_max_supported_pagesize, &hpsize);
+ object_child_foreach(memdev_root, find_min_backend_pagesize, &hpsize);
}
if (hpsize == LONG_MAX) {
/* No additional memory regions found ==> Report main RAM page size */
@@ -1747,8 +1771,24 @@ long qemu_getrampagesize(void)
return hpsize;
}
+
+long qemu_maxrampagesize(void)
+{
+ long pagesize = qemu_mempath_getpagesize(mem_path);
+ Object *memdev_root = object_resolve_path("/objects", NULL);
+
+ if (memdev_root) {
+ object_child_foreach(memdev_root, find_max_backend_pagesize,
+ &pagesize);
+ }
+ return pagesize;
+}
#else
-long qemu_getrampagesize(void)
+long qemu_minrampagesize(void)
+{
+ return getpagesize();
+}
+long qemu_maxrampagesize(void)
{
return getpagesize();
}
@@ -1879,7 +1919,7 @@ static void *file_ram_alloc(RAMBlock *block,
}
area = qemu_ram_mmap(fd, memory, block->mr->align,
- block->flags & RAM_SHARED);
+ block->flags & RAM_SHARED, block->flags & RAM_PMEM);
if (area == MAP_FAILED) {
error_setg_errno(errp, errno,
"unable to map backing store for guest RAM");
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index ce2664a30b..16ba67f7a7 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1978,10 +1978,17 @@ static void machvirt_machine_init(void)
}
type_init(machvirt_machine_init);
+static void virt_machine_4_1_options(MachineClass *mc)
+{
+}
+DEFINE_VIRT_MACHINE_AS_LATEST(4, 1)
+
static void virt_machine_4_0_options(MachineClass *mc)
{
+ virt_machine_4_1_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
}
-DEFINE_VIRT_MACHINE_AS_LATEST(4, 0)
+DEFINE_VIRT_MACHINE(4, 0)
static void virt_machine_3_1_options(MachineClass *mc)
{
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 743fef2898..5d046a43e3 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -24,6 +24,9 @@
#include "hw/pci/pci.h"
#include "hw/mem/nvdimm.h"
+GlobalProperty hw_compat_4_0[] = {};
+const size_t hw_compat_4_0_len = G_N_ELEMENTS(hw_compat_4_0);
+
GlobalProperty hw_compat_3_1[] = {
{ "pcie-root-port", "x-speed", "2_5" },
{ "pcie-root-port", "x-width", "1" },
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 6eabdf9917..4a4e2c7fd4 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -1601,6 +1601,8 @@ static void amdvi_class_init(ObjectClass *klass, void* data)
dc_class->int_remap = amdvi_int_remap;
/* Supported by the pc-q35-* machine types */
dc->user_creatable = true;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ dc->desc = "AMD IOMMU (AMD-Vi) DMA Remapping device";
}
static const TypeInfo amdvi = {
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 2558f48fe6..44b1231157 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3741,6 +3741,8 @@ static void vtd_class_init(ObjectClass *klass, void *data)
x86_class->int_remap = vtd_int_remap;
/* Supported by the pc-q35-* machine types */
dc->user_creatable = true;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ dc->desc = "Intel IOMMU (VT-d) DMA Remapping device";
}
static const TypeInfo vtd_info = {
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index f2c15bf1f2..d98b737b8f 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -115,6 +115,9 @@ struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
/* Physical Address of PVH entry point read from kernel ELF NOTE */
static size_t pvh_start_addr;
+GlobalProperty pc_compat_4_0[] = {};
+const size_t pc_compat_4_0_len = G_N_ELEMENTS(pc_compat_4_0);
+
GlobalProperty pc_compat_3_1[] = {
{ "intel-iommu", "dma-drain", "off" },
{ "Opteron_G3" "-" TYPE_X86_CPU, "rdtscp", "off" },
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 8ad8e885c6..c07c4a5b38 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -428,13 +428,25 @@ static void pc_i440fx_machine_options(MachineClass *m)
machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE);
}
-static void pc_i440fx_4_0_machine_options(MachineClass *m)
+static void pc_i440fx_4_1_machine_options(MachineClass *m)
{
pc_i440fx_machine_options(m);
m->alias = "pc";
m->is_default = 1;
}
+DEFINE_I440FX_MACHINE(v4_1, "pc-i440fx-4.1", NULL,
+ pc_i440fx_4_1_machine_options);
+
+static void pc_i440fx_4_0_machine_options(MachineClass *m)
+{
+ pc_i440fx_4_1_machine_options(m);
+ m->alias = NULL;
+ m->is_default = 0;
+ compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
+ compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
+}
+
DEFINE_I440FX_MACHINE(v4_0, "pc-i440fx-4.0", NULL,
pc_i440fx_4_0_machine_options);
@@ -911,6 +923,7 @@ static void isa_bridge_class_init(ObjectClass *klass, void *data)
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
dc->desc = "ISA bridge faked to support IGD PT";
+ set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->class_id = PCI_CLASS_BRIDGE_ISA;
};
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 372c6b73be..37dd350511 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -365,12 +365,23 @@ static void pc_q35_machine_options(MachineClass *m)
m->max_cpus = 288;
}
-static void pc_q35_4_0_machine_options(MachineClass *m)
+static void pc_q35_4_1_machine_options(MachineClass *m)
{
pc_q35_machine_options(m);
m->alias = "q35";
}
+DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL,
+ pc_q35_4_1_machine_options);
+
+static void pc_q35_4_0_machine_options(MachineClass *m)
+{
+ pc_q35_4_1_machine_options(m);
+ m->alias = NULL;
+ compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
+ compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
+}
+
DEFINE_Q35_MACHINE(v4_0, "pc-q35-4.0", NULL,
pc_q35_4_0_machine_options);
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 1808b242dd..a78023f669 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1556,7 +1556,7 @@ void pci_device_set_intx_routing_notifier(PCIDevice *dev,
*/
int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin)
{
- return (pin + PCI_SLOT(pci_dev->devfn)) % PCI_NUM_PINS;
+ return pci_swizzle(PCI_SLOT(pci_dev->devfn), pin);
}
/***********************************************************/
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index 1111b218a0..636e717f20 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -9,7 +9,7 @@ obj-$(CONFIG_SPAPR_RNG) += spapr_rng.o
# IBM PowerNV
obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_core.o pnv_lpc.o pnv_psi.o pnv_occ.o pnv_bmc.o
ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy)
-obj-y += spapr_pci_vfio.o
+obj-y += spapr_pci_vfio.o spapr_pci_nvlink2.o
endif
obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
# PowerPC 4xx boards
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index 847d320465..b7f459d475 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -40,7 +40,6 @@
#include "hw/ide.h"
#include "hw/loader.h"
#include "hw/timer/mc146818rtc.h"
-#include "hw/input/i8042.h"
#include "hw/isa/pc87312.h"
#include "hw/net/ne2000-isa.h"
#include "sysemu/arch_init.h"
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index b52b82d298..2ef3ce4362 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1034,12 +1034,13 @@ static void spapr_dt_rtas(SpaprMachineState *spapr, void *fdt)
0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE),
cpu_to_be32(max_cpus / smp_threads),
};
+ uint32_t maxdomain = cpu_to_be32(spapr->gpu_numa_id > 1 ? 1 : 0);
uint32_t maxdomains[] = {
cpu_to_be32(4),
- cpu_to_be32(0),
- cpu_to_be32(0),
- cpu_to_be32(0),
- cpu_to_be32(nb_numa_nodes ? nb_numa_nodes : 1),
+ maxdomain,
+ maxdomain,
+ maxdomain,
+ cpu_to_be32(spapr->gpu_numa_id),
};
_FDT(rtas = fdt_add_subnode(fdt, 0, "rtas"));
@@ -1519,10 +1520,10 @@ static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp,
/* Nothing to do for qemu managed HPT */
}
-static void spapr_store_hpte(PPCVirtualHypervisor *vhyp, hwaddr ptex,
- uint64_t pte0, uint64_t pte1)
+void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
+ uint64_t pte0, uint64_t pte1)
{
- SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
+ SpaprMachineState *spapr = SPAPR_MACHINE(cpu->vhyp);
hwaddr offset = ptex * HASH_PTE_SIZE_64;
if (!spapr->htab) {
@@ -1550,6 +1551,38 @@ static void spapr_store_hpte(PPCVirtualHypervisor *vhyp, hwaddr ptex,
}
}
+static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex,
+ uint64_t pte1)
+{
+ hwaddr offset = ptex * HASH_PTE_SIZE_64 + 15;
+ SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
+
+ if (!spapr->htab) {
+ /* There should always be a hash table when this is called */
+ error_report("spapr_hpte_set_c called with no hash table !");
+ return;
+ }
+
+ /* The HW performs a non-atomic byte update */
+ stb_p(spapr->htab + offset, (pte1 & 0xff) | 0x80);
+}
+
+static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex,
+ uint64_t pte1)
+{
+ hwaddr offset = ptex * HASH_PTE_SIZE_64 + 14;
+ SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
+
+ if (!spapr->htab) {
+ /* There should always be a hash table when this is called */
+ error_report("spapr_hpte_set_r called with no hash table !");
+ return;
+ }
+
+ /* The HW performs a non-atomic byte update */
+ stb_p(spapr->htab + offset, ((pte1 >> 8) & 0xff) | 0x01);
+}
+
int spapr_hpt_shift_for_ramsize(uint64_t ramsize)
{
int shift;
@@ -1698,6 +1731,16 @@ static void spapr_machine_reset(void)
spapr_irq_msi_reset(spapr);
}
+ /*
+ * NVLink2-connected GPU RAM needs to be placed on a separate NUMA node.
+ * We assign a new numa ID per GPU in spapr_pci_collect_nvgpu() which is
+ * called from vPHB reset handler so we initialize the counter here.
+ * If no NUMA is configured from the QEMU side, we start from 1 as GPU RAM
+ * must be equally distant from any other node.
+ * The final value of spapr->gpu_numa_id is going to be written to
+ * max-associativity-domains in spapr_build_fdt().
+ */
+ spapr->gpu_numa_id = MAX(1, nb_numa_nodes);
qemu_devices_reset();
/*
@@ -3907,7 +3950,9 @@ static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
smc->phb_placement(spapr, sphb->index,
&sphb->buid, &sphb->io_win_addr,
&sphb->mem_win_addr, &sphb->mem64_win_addr,
- windows_supported, sphb->dma_liobn, errp);
+ windows_supported, sphb->dma_liobn,
+ &sphb->nv2_gpa_win_addr, &sphb->nv2_atsd_win_addr,
+ errp);
}
static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
@@ -4108,7 +4153,8 @@ static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine)
static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index,
uint64_t *buid, hwaddr *pio,
hwaddr *mmio32, hwaddr *mmio64,
- unsigned n_dma, uint32_t *liobns, Error **errp)
+ unsigned n_dma, uint32_t *liobns,
+ hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp)
{
/*
* New-style PHB window placement.
@@ -4153,6 +4199,9 @@ static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index,
*pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE;
*mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE;
*mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE;
+
+ *nv2gpa = SPAPR_PCI_NV2RAM64_WIN_BASE + index * SPAPR_PCI_NV2RAM64_WIN_SIZE;
+ *nv2atsd = SPAPR_PCI_NV2ATSD_WIN_BASE + index * SPAPR_PCI_NV2ATSD_WIN_SIZE;
}
static ICSState *spapr_ics_get(XICSFabric *dev, int irq)
@@ -4274,7 +4323,8 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
vhc->hpt_mask = spapr_hpt_mask;
vhc->map_hptes = spapr_map_hptes;
vhc->unmap_hptes = spapr_unmap_hptes;
- vhc->store_hpte = spapr_store_hpte;
+ vhc->hpte_set_c = spapr_hpte_set_c;
+ vhc->hpte_set_r = spapr_hpte_set_r;
vhc->get_pate = spapr_get_pate;
vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr;
xic->ics_get = spapr_ics_get;
@@ -4345,18 +4395,41 @@ static const TypeInfo spapr_machine_info = {
type_init(spapr_machine_register_##suffix)
/*
+ * pseries-4.1
+ */
+static void spapr_machine_4_1_class_options(MachineClass *mc)
+{
+ /* Defaults for the latest behaviour inherited from the base class */
+}
+
+DEFINE_SPAPR_MACHINE(4_1, "4.1", true);
+
+/*
* pseries-4.0
*/
static void spapr_machine_4_0_class_options(MachineClass *mc)
{
- /* Defaults for the latest behaviour inherited from the base class */
+ spapr_machine_4_1_class_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
}
-DEFINE_SPAPR_MACHINE(4_0, "4.0", true);
+DEFINE_SPAPR_MACHINE(4_0, "4.0", false);
/*
* pseries-3.1
*/
+static void phb_placement_3_1(SpaprMachineState *spapr, uint32_t index,
+ uint64_t *buid, hwaddr *pio,
+ hwaddr *mmio32, hwaddr *mmio64,
+ unsigned n_dma, uint32_t *liobns,
+ hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp)
+{
+ spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, liobns,
+ nv2gpa, nv2atsd, errp);
+ *nv2gpa = 0;
+ *nv2atsd = 0;
+}
+
static void spapr_machine_3_1_class_options(MachineClass *mc)
{
SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
@@ -4372,6 +4445,7 @@ static void spapr_machine_3_1_class_options(MachineClass *mc)
smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
+ smc->phb_placement = phb_placement_3_1;
}
DEFINE_SPAPR_MACHINE(3_1, "3.1", false);
@@ -4503,7 +4577,8 @@ DEFINE_SPAPR_MACHINE(2_8, "2.8", false);
static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index,
uint64_t *buid, hwaddr *pio,
hwaddr *mmio32, hwaddr *mmio64,
- unsigned n_dma, uint32_t *liobns, Error **errp)
+ unsigned n_dma, uint32_t *liobns,
+ hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp)
{
/* Legacy PHB placement for pseries-2.7 and earlier machine types */
const uint64_t base_buid = 0x800000020000000ULL;
@@ -4547,6 +4622,9 @@ static void phb_placement_2_7(SpaprMachineState *spapr, uint32_t index,
* fallback behaviour of automatically splitting a large "32-bit"
* window into contiguous 32-bit and 64-bit windows
*/
+
+ *nv2gpa = 0;
+ *nv2atsd = 0;
}
static void spapr_machine_2_7_class_options(MachineClass *mc)
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index edc5ed0e0c..9b1c10baa6 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -347,7 +347,7 @@ static void cap_hpt_maxpagesize_apply(SpaprMachineState *spapr,
warn_report("Many guests require at least 64kiB hpt-max-page-size");
}
- spapr_check_pagesize(spapr, qemu_getrampagesize(), errp);
+ spapr_check_pagesize(spapr, qemu_minrampagesize(), errp);
}
static bool spapr_pagesize_cb(void *opaque, uint32_t seg_pshift,
@@ -609,7 +609,7 @@ static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
uint8_t mps;
if (kvmppc_hpt_needs_host_contiguous_pages()) {
- mps = ctz64(qemu_getrampagesize());
+ mps = ctz64(qemu_minrampagesize());
} else {
mps = 34; /* allow everything up to 16GiB, i.e. everything */
}
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 8a736797b9..6c16d2b120 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -118,7 +118,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, SpaprMachineState *spapr,
ppc_hash64_unmap_hptes(cpu, hptes, ptex, 1);
}
- ppc_hash64_store_hpte(cpu, ptex + slot, pteh | HPTE64_V_HPTE_DIRTY, ptel);
+ spapr_store_hpte(cpu, ptex + slot, pteh | HPTE64_V_HPTE_DIRTY, ptel);
args[0] = ptex + slot;
return H_SUCCESS;
@@ -131,7 +131,8 @@ typedef enum {
REMOVE_HW = 3,
} RemoveResult;
-static RemoveResult remove_hpte(PowerPCCPU *cpu, target_ulong ptex,
+static RemoveResult remove_hpte(PowerPCCPU *cpu
+ , target_ulong ptex,
target_ulong avpn,
target_ulong flags,
target_ulong *vp, target_ulong *rp)
@@ -155,7 +156,7 @@ static RemoveResult remove_hpte(PowerPCCPU *cpu, target_ulong ptex,
}
*vp = v;
*rp = r;
- ppc_hash64_store_hpte(cpu, ptex, HPTE64_V_HPTE_DIRTY, 0);
+ spapr_store_hpte(cpu, ptex, HPTE64_V_HPTE_DIRTY, 0);
ppc_hash64_tlb_flush_hpte(cpu, ptex, v, r);
return REMOVE_SUCCESS;
}
@@ -289,13 +290,13 @@ static target_ulong h_protect(PowerPCCPU *cpu, SpaprMachineState *spapr,
r |= (flags << 55) & HPTE64_R_PP0;
r |= (flags << 48) & HPTE64_R_KEY_HI;
r |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO);
- ppc_hash64_store_hpte(cpu, ptex,
- (v & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY, 0);
+ spapr_store_hpte(cpu, ptex,
+ (v & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY, 0);
ppc_hash64_tlb_flush_hpte(cpu, ptex, v, r);
/* Flush the tlb */
check_tlb_flush(env, true);
/* Don't need a memory barrier, due to qemu's global lock */
- ppc_hash64_store_hpte(cpu, ptex, v | HPTE64_V_HPTE_DIRTY, r);
+ spapr_store_hpte(cpu, ptex, v | HPTE64_V_HPTE_DIRTY, r);
return H_SUCCESS;
}
@@ -304,8 +305,8 @@ static target_ulong h_read(PowerPCCPU *cpu, SpaprMachineState *spapr,
{
target_ulong flags = args[0];
target_ulong ptex = args[1];
- uint8_t *hpte;
int i, ridx, n_entries = 1;
+ const ppc_hash_pte64_t *hptes;
if (!valid_ptex(cpu, ptex)) {
return H_PARAMETER;
@@ -317,13 +318,12 @@ static target_ulong h_read(PowerPCCPU *cpu, SpaprMachineState *spapr,
n_entries = 4;
}
- hpte = spapr->htab + (ptex * HASH_PTE_SIZE_64);
-
+ hptes = ppc_hash64_map_hptes(cpu, ptex, n_entries);
for (i = 0, ridx = 0; i < n_entries; i++) {
- args[ridx++] = ldq_p(hpte);
- args[ridx++] = ldq_p(hpte + (HASH_PTE_SIZE_64/2));
- hpte += HASH_PTE_SIZE_64;
+ args[ridx++] = ppc_hash64_hpte0(cpu, hptes, i);
+ args[ridx++] = ppc_hash64_hpte1(cpu, hptes, i);
}
+ ppc_hash64_unmap_hptes(cpu, hptes, ptex, n_entries);
return H_SUCCESS;
}
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 0a84e4cf63..b1f79ea9de 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -67,36 +67,11 @@ void spapr_irq_msi_reset(SpaprMachineState *spapr)
* XICS IRQ backend.
*/
-static ICSState *spapr_ics_create(SpaprMachineState *spapr,
- int nr_irqs, Error **errp)
-{
- Error *local_err = NULL;
- Object *obj;
-
- obj = object_new(TYPE_ICS_SIMPLE);
- object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort);
- object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr),
- &error_abort);
- object_property_set_int(obj, nr_irqs, "nr-irqs", &local_err);
- if (local_err) {
- goto error;
- }
- object_property_set_bool(obj, true, "realized", &local_err);
- if (local_err) {
- goto error;
- }
-
- return ICS_BASE(obj);
-
-error:
- error_propagate(errp, local_err);
- return NULL;
-}
-
static void spapr_irq_init_xics(SpaprMachineState *spapr, int nr_irqs,
Error **errp)
{
MachineState *machine = MACHINE(spapr);
+ Object *obj;
Error *local_err = NULL;
bool xics_kvm = false;
@@ -108,7 +83,8 @@ static void spapr_irq_init_xics(SpaprMachineState *spapr, int nr_irqs,
if (machine_kernel_irqchip_required(machine) && !xics_kvm) {
error_prepend(&local_err,
"kernel_irqchip requested but unavailable: ");
- goto error;
+ error_propagate(errp, local_err);
+ return;
}
error_free(local_err);
local_err = NULL;
@@ -118,10 +94,18 @@ static void spapr_irq_init_xics(SpaprMachineState *spapr, int nr_irqs,
xics_spapr_init(spapr);
}
- spapr->ics = spapr_ics_create(spapr, nr_irqs, &local_err);
+ obj = object_new(TYPE_ICS_SIMPLE);
+ object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort);
+ object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr),
+ &error_fatal);
+ object_property_set_int(obj, nr_irqs, "nr-irqs", &error_fatal);
+ object_property_set_bool(obj, true, "realized", &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
-error:
- error_propagate(errp, local_err);
+ spapr->ics = ICS_BASE(obj);
}
#define ICS_IRQ_FREE(ics, srcno) \
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index f62e6833b8..97961b0128 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -719,26 +719,10 @@ param_error_exit:
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
}
-static int pci_spapr_swizzle(int slot, int pin)
-{
- return (slot + pin) % PCI_NUM_PINS;
-}
-
-static int pci_spapr_map_irq(PCIDevice *pci_dev, int irq_num)
-{
- /*
- * Here we need to convert pci_dev + irq_num to some unique value
- * which is less than number of IRQs on the specific bus (4). We
- * use standard PCI swizzling, that is (slot number + pin number)
- * % 4.
- */
- return pci_spapr_swizzle(PCI_SLOT(pci_dev->devfn), irq_num);
-}
-
static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
{
/*
- * Here we use the number returned by pci_spapr_map_irq to find a
+ * Here we use the number returned by pci_swizzle_map_irq_fn to find a
* corresponding qemu_irq.
*/
SpaprPhbState *phb = opaque;
@@ -1355,6 +1339,8 @@ static void spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset,
if (sphb->pcie_ecs && pci_is_express(dev)) {
_FDT(fdt_setprop_cell(fdt, offset, "ibm,pci-config-space-type", 0x1));
}
+
+ spapr_phb_nvgpu_populate_pcidev_dt(dev, fdt, offset, sphb);
}
/* create OF node for pci device and required OF DT properties */
@@ -1587,6 +1573,8 @@ static void spapr_phb_unrealize(DeviceState *dev, Error **errp)
int i;
const unsigned windows_supported = spapr_phb_windows_supported(sphb);
+ spapr_phb_nvgpu_free(sphb);
+
if (sphb->msi) {
g_hash_table_unref(sphb->msi);
sphb->msi = NULL;
@@ -1762,7 +1750,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
&sphb->iowindow);
bus = pci_register_root_bus(dev, NULL,
- pci_spapr_set_irq, pci_spapr_map_irq, sphb,
+ pci_spapr_set_irq, pci_swizzle_map_irq_fn, sphb,
&sphb->memspace, &sphb->iospace,
PCI_DEVFN(0, 0), PCI_NUM_PINS,
TYPE_SPAPR_PHB_ROOT_BUS);
@@ -1898,8 +1886,14 @@ void spapr_phb_dma_reset(SpaprPhbState *sphb)
static void spapr_phb_reset(DeviceState *qdev)
{
SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(qdev);
+ Error *errp = NULL;
spapr_phb_dma_reset(sphb);
+ spapr_phb_nvgpu_free(sphb);
+ spapr_phb_nvgpu_setup(sphb, &errp);
+ if (errp) {
+ error_report_err(errp);
+ }
/* Reset the IOMMU state */
object_child_foreach(OBJECT(qdev), spapr_phb_children_reset, NULL);
@@ -1932,6 +1926,8 @@ static Property spapr_phb_properties[] = {
pre_2_8_migration, false),
DEFINE_PROP_BOOL("pcie-extended-configuration-space", SpaprPhbState,
pcie_ecs, true),
+ DEFINE_PROP_UINT64("gpa", SpaprPhbState, nv2_gpa_win_addr, 0),
+ DEFINE_PROP_UINT64("atsd", SpaprPhbState, nv2_atsd_win_addr, 0),
DEFINE_PROP_END_OF_LIST(),
};
@@ -2164,7 +2160,6 @@ int spapr_populate_pci_dt(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
uint32_t nr_msis, int *node_offset)
{
int bus_off, i, j, ret;
- gchar *nodename;
uint32_t bus_range[] = { cpu_to_be32(0), cpu_to_be32(0xff) };
struct {
uint32_t hi;
@@ -2212,11 +2207,10 @@ int spapr_populate_pci_dt(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
PCIBus *bus = PCI_HOST_BRIDGE(phb)->bus;
SpaprFdt s_fdt;
SpaprDrc *drc;
+ Error *errp = NULL;
/* Start populating the FDT */
- nodename = g_strdup_printf("pci@%" PRIx64, phb->buid);
- _FDT(bus_off = fdt_add_subnode(fdt, 0, nodename));
- g_free(nodename);
+ _FDT(bus_off = fdt_add_subnode(fdt, 0, phb->dtbusname));
if (node_offset) {
*node_offset = bus_off;
}
@@ -2249,14 +2243,14 @@ int spapr_populate_pci_dt(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
}
/* Build the interrupt-map, this must matches what is done
- * in pci_spapr_map_irq
+ * in pci_swizzle_map_irq_fn
*/
_FDT(fdt_setprop(fdt, bus_off, "interrupt-map-mask",
&interrupt_map_mask, sizeof(interrupt_map_mask)));
for (i = 0; i < PCI_SLOT_MAX; i++) {
for (j = 0; j < PCI_NUM_PINS; j++) {
uint32_t *irqmap = interrupt_map[i*PCI_NUM_PINS + j];
- int lsi_num = pci_spapr_swizzle(i, j);
+ int lsi_num = pci_swizzle(i, j);
irqmap[0] = cpu_to_be32(b_ddddd(i)|b_fff(0));
irqmap[1] = 0;
@@ -2304,6 +2298,12 @@ int spapr_populate_pci_dt(SpaprPhbState *phb, uint32_t intc_phandle, void *fdt,
return ret;
}
+ spapr_phb_nvgpu_populate_dt(phb, fdt, bus_off, &errp);
+ if (errp) {
+ error_report_err(errp);
+ }
+ spapr_phb_nvgpu_ram_populate_dt(phb, fdt);
+
return 0;
}
diff --git a/hw/ppc/spapr_pci_nvlink2.c b/hw/ppc/spapr_pci_nvlink2.c
new file mode 100644
index 0000000000..eda8c752aa
--- /dev/null
+++ b/hw/ppc/spapr_pci_nvlink2.c
@@ -0,0 +1,450 @@
+/*
+ * QEMU sPAPR PCI for NVLink2 pass through
+ *
+ * Copyright (c) 2019 Alexey Kardashevskiy, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/pci/pci.h"
+#include "hw/pci-host/spapr.h"
+#include "qemu/error-report.h"
+#include "hw/ppc/fdt.h"
+#include "hw/pci/pci_bridge.h"
+
+#define PHANDLE_PCIDEV(phb, pdev) (0x12000000 | \
+ (((phb)->index) << 16) | ((pdev)->devfn))
+#define PHANDLE_GPURAM(phb, n) (0x110000FF | ((n) << 8) | \
+ (((phb)->index) << 16))
+#define PHANDLE_NVLINK(phb, gn, nn) (0x00130000 | (((phb)->index) << 8) | \
+ ((gn) << 4) | (nn))
+
+#define SPAPR_GPU_NUMA_ID (cpu_to_be32(1))
+
+struct spapr_phb_pci_nvgpu_config {
+ uint64_t nv2_ram_current;
+ uint64_t nv2_atsd_current;
+ int num; /* number of non empty (i.e. tgt!=0) entries in slots[] */
+ struct spapr_phb_pci_nvgpu_slot {
+ uint64_t tgt;
+ uint64_t gpa;
+ unsigned numa_id;
+ PCIDevice *gpdev;
+ int linknum;
+ struct {
+ uint64_t atsd_gpa;
+ PCIDevice *npdev;
+ uint32_t link_speed;
+ } links[NVGPU_MAX_LINKS];
+ } slots[NVGPU_MAX_NUM];
+ Error *errp;
+};
+
+static struct spapr_phb_pci_nvgpu_slot *
+spapr_nvgpu_get_slot(struct spapr_phb_pci_nvgpu_config *nvgpus, uint64_t tgt)
+{
+ int i;
+
+ /* Search for partially collected "slot" */
+ for (i = 0; i < nvgpus->num; ++i) {
+ if (nvgpus->slots[i].tgt == tgt) {
+ return &nvgpus->slots[i];
+ }
+ }
+
+ if (nvgpus->num == ARRAY_SIZE(nvgpus->slots)) {
+ return NULL;
+ }
+
+ i = nvgpus->num;
+ nvgpus->slots[i].tgt = tgt;
+ ++nvgpus->num;
+
+ return &nvgpus->slots[i];
+}
+
+static void spapr_pci_collect_nvgpu(struct spapr_phb_pci_nvgpu_config *nvgpus,
+ PCIDevice *pdev, uint64_t tgt,
+ MemoryRegion *mr, Error **errp)
+{
+ MachineState *machine = MACHINE(qdev_get_machine());
+ SpaprMachineState *spapr = SPAPR_MACHINE(machine);
+ struct spapr_phb_pci_nvgpu_slot *nvslot = spapr_nvgpu_get_slot(nvgpus, tgt);
+
+ if (!nvslot) {
+ error_setg(errp, "Found too many GPUs per vPHB");
+ return;
+ }
+ g_assert(!nvslot->gpdev);
+ nvslot->gpdev = pdev;
+
+ nvslot->gpa = nvgpus->nv2_ram_current;
+ nvgpus->nv2_ram_current += memory_region_size(mr);
+ nvslot->numa_id = spapr->gpu_numa_id;
+ ++spapr->gpu_numa_id;
+}
+
+static void spapr_pci_collect_nvnpu(struct spapr_phb_pci_nvgpu_config *nvgpus,
+ PCIDevice *pdev, uint64_t tgt,
+ MemoryRegion *mr, Error **errp)
+{
+ struct spapr_phb_pci_nvgpu_slot *nvslot = spapr_nvgpu_get_slot(nvgpus, tgt);
+ int j;
+
+ if (!nvslot) {
+ error_setg(errp, "Found too many NVLink bridges per vPHB");
+ return;
+ }
+
+ j = nvslot->linknum;
+ if (j == ARRAY_SIZE(nvslot->links)) {
+ error_setg(errp, "Found too many NVLink bridges per GPU");
+ return;
+ }
+ ++nvslot->linknum;
+
+ g_assert(!nvslot->links[j].npdev);
+ nvslot->links[j].npdev = pdev;
+ nvslot->links[j].atsd_gpa = nvgpus->nv2_atsd_current;
+ nvgpus->nv2_atsd_current += memory_region_size(mr);
+ nvslot->links[j].link_speed =
+ object_property_get_uint(OBJECT(pdev), "nvlink2-link-speed", NULL);
+}
+
+static void spapr_phb_pci_collect_nvgpu(PCIBus *bus, PCIDevice *pdev,
+ void *opaque)
+{
+ PCIBus *sec_bus;
+ Object *po = OBJECT(pdev);
+ uint64_t tgt = object_property_get_uint(po, "nvlink2-tgt", NULL);
+
+ if (tgt) {
+ Error *local_err = NULL;
+ struct spapr_phb_pci_nvgpu_config *nvgpus = opaque;
+ Object *mr_gpu = object_property_get_link(po, "nvlink2-mr[0]", NULL);
+ Object *mr_npu = object_property_get_link(po, "nvlink2-atsd-mr[0]",
+ NULL);
+
+ g_assert(mr_gpu || mr_npu);
+ if (mr_gpu) {
+ spapr_pci_collect_nvgpu(nvgpus, pdev, tgt, MEMORY_REGION(mr_gpu),
+ &local_err);
+ } else {
+ spapr_pci_collect_nvnpu(nvgpus, pdev, tgt, MEMORY_REGION(mr_npu),
+ &local_err);
+ }
+ error_propagate(&nvgpus->errp, local_err);
+ }
+ if ((pci_default_read_config(pdev, PCI_HEADER_TYPE, 1) !=
+ PCI_HEADER_TYPE_BRIDGE)) {
+ return;
+ }
+
+ sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev));
+ if (!sec_bus) {
+ return;
+ }
+
+ pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
+ spapr_phb_pci_collect_nvgpu, opaque);
+}
+
+void spapr_phb_nvgpu_setup(SpaprPhbState *sphb, Error **errp)
+{
+ int i, j, valid_gpu_num;
+ PCIBus *bus;
+
+ /* Search for GPUs and NPUs */
+ if (!sphb->nv2_gpa_win_addr || !sphb->nv2_atsd_win_addr) {
+ return;
+ }
+
+ sphb->nvgpus = g_new0(struct spapr_phb_pci_nvgpu_config, 1);
+ sphb->nvgpus->nv2_ram_current = sphb->nv2_gpa_win_addr;
+ sphb->nvgpus->nv2_atsd_current = sphb->nv2_atsd_win_addr;
+
+ bus = PCI_HOST_BRIDGE(sphb)->bus;
+ pci_for_each_device(bus, pci_bus_num(bus),
+ spapr_phb_pci_collect_nvgpu, sphb->nvgpus);
+
+ if (sphb->nvgpus->errp) {
+ error_propagate(errp, sphb->nvgpus->errp);
+ sphb->nvgpus->errp = NULL;
+ goto cleanup_exit;
+ }
+
+ /* Add found GPU RAM and ATSD MRs if found */
+ for (i = 0, valid_gpu_num = 0; i < sphb->nvgpus->num; ++i) {
+ Object *nvmrobj;
+ struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i];
+
+ if (!nvslot->gpdev) {
+ continue;
+ }
+ nvmrobj = object_property_get_link(OBJECT(nvslot->gpdev),
+ "nvlink2-mr[0]", NULL);
+ /* ATSD is pointless without GPU RAM MR so skip those */
+ if (!nvmrobj) {
+ continue;
+ }
+
+ ++valid_gpu_num;
+ memory_region_add_subregion(get_system_memory(), nvslot->gpa,
+ MEMORY_REGION(nvmrobj));
+
+ for (j = 0; j < nvslot->linknum; ++j) {
+ Object *atsdmrobj;
+
+ atsdmrobj = object_property_get_link(OBJECT(nvslot->links[j].npdev),
+ "nvlink2-atsd-mr[0]", NULL);
+ if (!atsdmrobj) {
+ continue;
+ }
+ memory_region_add_subregion(get_system_memory(),
+ nvslot->links[j].atsd_gpa,
+ MEMORY_REGION(atsdmrobj));
+ }
+ }
+
+ if (valid_gpu_num) {
+ return;
+ }
+ /* We did not find any interesting GPU */
+cleanup_exit:
+ g_free(sphb->nvgpus);
+ sphb->nvgpus = NULL;
+}
+
+void spapr_phb_nvgpu_free(SpaprPhbState *sphb)
+{
+ int i, j;
+
+ if (!sphb->nvgpus) {
+ return;
+ }
+
+ for (i = 0; i < sphb->nvgpus->num; ++i) {
+ struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i];
+ Object *nv_mrobj = object_property_get_link(OBJECT(nvslot->gpdev),
+ "nvlink2-mr[0]", NULL);
+
+ if (nv_mrobj) {
+ memory_region_del_subregion(get_system_memory(),
+ MEMORY_REGION(nv_mrobj));
+ }
+ for (j = 0; j < nvslot->linknum; ++j) {
+ PCIDevice *npdev = nvslot->links[j].npdev;
+ Object *atsd_mrobj;
+ atsd_mrobj = object_property_get_link(OBJECT(npdev),
+ "nvlink2-atsd-mr[0]", NULL);
+ if (atsd_mrobj) {
+ memory_region_del_subregion(get_system_memory(),
+ MEMORY_REGION(atsd_mrobj));
+ }
+ }
+ }
+ g_free(sphb->nvgpus);
+ sphb->nvgpus = NULL;
+}
+
+void spapr_phb_nvgpu_populate_dt(SpaprPhbState *sphb, void *fdt, int bus_off,
+ Error **errp)
+{
+ int i, j, atsdnum = 0;
+ uint64_t atsd[8]; /* The existing limitation of known guests */
+
+ if (!sphb->nvgpus) {
+ return;
+ }
+
+ for (i = 0; (i < sphb->nvgpus->num) && (atsdnum < ARRAY_SIZE(atsd)); ++i) {
+ struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i];
+
+ if (!nvslot->gpdev) {
+ continue;
+ }
+ for (j = 0; j < nvslot->linknum; ++j) {
+ if (!nvslot->links[j].atsd_gpa) {
+ continue;
+ }
+
+ if (atsdnum == ARRAY_SIZE(atsd)) {
+ error_report("Only %"PRIuPTR" ATSD registers supported",
+ ARRAY_SIZE(atsd));
+ break;
+ }
+ atsd[atsdnum] = cpu_to_be64(nvslot->links[j].atsd_gpa);
+ ++atsdnum;
+ }
+ }
+
+ if (!atsdnum) {
+ error_setg(errp, "No ATSD registers found");
+ return;
+ }
+
+ if (!spapr_phb_eeh_available(sphb)) {
+ /*
+ * ibm,mmio-atsd contains ATSD registers; these belong to an NPU PHB
+ * which we do not emulate as a separate device. Instead we put
+ * ibm,mmio-atsd to the vPHB with GPU and make sure that we do not
+ * put GPUs from different IOMMU groups to the same vPHB to ensure
+ * that the guest will use ATSDs from the corresponding NPU.
+ */
+ error_setg(errp, "ATSD requires separate vPHB per GPU IOMMU group");
+ return;
+ }
+
+ _FDT((fdt_setprop(fdt, bus_off, "ibm,mmio-atsd", atsd,
+ atsdnum * sizeof(atsd[0]))));
+}
+
+void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt)
+{
+ int i, j, linkidx, npuoff;
+ char *npuname;
+
+ if (!sphb->nvgpus) {
+ return;
+ }
+
+ npuname = g_strdup_printf("npuphb%d", sphb->index);
+ npuoff = fdt_add_subnode(fdt, 0, npuname);
+ _FDT(npuoff);
+ _FDT(fdt_setprop_cell(fdt, npuoff, "#address-cells", 1));
+ _FDT(fdt_setprop_cell(fdt, npuoff, "#size-cells", 0));
+ /* Advertise NPU as POWER9 so the guest can enable NPU2 contexts */
+ _FDT((fdt_setprop_string(fdt, npuoff, "compatible", "ibm,power9-npu")));
+ g_free(npuname);
+
+ for (i = 0, linkidx = 0; i < sphb->nvgpus->num; ++i) {
+ for (j = 0; j < sphb->nvgpus->slots[i].linknum; ++j) {
+ char *linkname = g_strdup_printf("link@%d", linkidx);
+ int off = fdt_add_subnode(fdt, npuoff, linkname);
+
+ _FDT(off);
+ /* _FDT((fdt_setprop_cell(fdt, off, "reg", linkidx))); */
+ _FDT((fdt_setprop_string(fdt, off, "compatible",
+ "ibm,npu-link")));
+ _FDT((fdt_setprop_cell(fdt, off, "phandle",
+ PHANDLE_NVLINK(sphb, i, j))));
+ _FDT((fdt_setprop_cell(fdt, off, "ibm,npu-link-index", linkidx)));
+ g_free(linkname);
+ ++linkidx;
+ }
+ }
+
+ /* Add memory nodes for GPU RAM and mark them unusable */
+ for (i = 0; i < sphb->nvgpus->num; ++i) {
+ struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i];
+ Object *nv_mrobj = object_property_get_link(OBJECT(nvslot->gpdev),
+ "nvlink2-mr[0]", NULL);
+ uint32_t associativity[] = {
+ cpu_to_be32(0x4),
+ SPAPR_GPU_NUMA_ID,
+ SPAPR_GPU_NUMA_ID,
+ SPAPR_GPU_NUMA_ID,
+ cpu_to_be32(nvslot->numa_id)
+ };
+ uint64_t size = object_property_get_uint(nv_mrobj, "size", NULL);
+ uint64_t mem_reg[2] = { cpu_to_be64(nvslot->gpa), cpu_to_be64(size) };
+ char *mem_name = g_strdup_printf("memory@%"PRIx64, nvslot->gpa);
+ int off = fdt_add_subnode(fdt, 0, mem_name);
+
+ _FDT(off);
+ _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
+ _FDT((fdt_setprop(fdt, off, "reg", mem_reg, sizeof(mem_reg))));
+ _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
+ sizeof(associativity))));
+
+ _FDT((fdt_setprop_string(fdt, off, "compatible",
+ "ibm,coherent-device-memory")));
+
+ mem_reg[1] = cpu_to_be64(0);
+ _FDT((fdt_setprop(fdt, off, "linux,usable-memory", mem_reg,
+ sizeof(mem_reg))));
+ _FDT((fdt_setprop_cell(fdt, off, "phandle",
+ PHANDLE_GPURAM(sphb, i))));
+ g_free(mem_name);
+ }
+
+}
+
+void spapr_phb_nvgpu_populate_pcidev_dt(PCIDevice *dev, void *fdt, int offset,
+ SpaprPhbState *sphb)
+{
+ int i, j;
+
+ if (!sphb->nvgpus) {
+ return;
+ }
+
+ for (i = 0; i < sphb->nvgpus->num; ++i) {
+ struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i];
+
+ /* Skip "slot" without attached GPU */
+ if (!nvslot->gpdev) {
+ continue;
+ }
+ if (dev == nvslot->gpdev) {
+ uint32_t npus[nvslot->linknum];
+
+ for (j = 0; j < nvslot->linknum; ++j) {
+ PCIDevice *npdev = nvslot->links[j].npdev;
+
+ npus[j] = cpu_to_be32(PHANDLE_PCIDEV(sphb, npdev));
+ }
+ _FDT(fdt_setprop(fdt, offset, "ibm,npu", npus,
+ j * sizeof(npus[0])));
+ _FDT((fdt_setprop_cell(fdt, offset, "phandle",
+ PHANDLE_PCIDEV(sphb, dev))));
+ continue;
+ }
+
+ for (j = 0; j < nvslot->linknum; ++j) {
+ if (dev != nvslot->links[j].npdev) {
+ continue;
+ }
+
+ _FDT((fdt_setprop_cell(fdt, offset, "phandle",
+ PHANDLE_PCIDEV(sphb, dev))));
+ _FDT(fdt_setprop_cell(fdt, offset, "ibm,gpu",
+ PHANDLE_PCIDEV(sphb, nvslot->gpdev)));
+ _FDT((fdt_setprop_cell(fdt, offset, "ibm,nvlink",
+ PHANDLE_NVLINK(sphb, i, j))));
+ /*
+ * If we ever want to emulate GPU RAM at the same location as on
+ * the host - here is the encoding GPA->TGT:
+ *
+ * gta = ((sphb->nv2_gpa >> 42) & 0x1) << 42;
+ * gta |= ((sphb->nv2_gpa >> 45) & 0x3) << 43;
+ * gta |= ((sphb->nv2_gpa >> 49) & 0x3) << 45;
+ * gta |= sphb->nv2_gpa & ((1UL << 43) - 1);
+ */
+ _FDT(fdt_setprop_cell(fdt, offset, "memory-region",
+ PHANDLE_GPURAM(sphb, i)));
+ _FDT(fdt_setprop_u64(fdt, offset, "ibm,device-tgt-addr",
+ nvslot->tgt));
+ _FDT(fdt_setprop_cell(fdt, offset, "ibm,nvlink-speed",
+ nvslot->links[j].link_speed));
+ }
+ }
+}
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 24c45b12d4..ee24212765 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -404,7 +404,7 @@ void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn)
token -= RTAS_TOKEN_BASE;
- assert(!rtas_table[token].name);
+ assert(!name || !rtas_table[token].name);
rtas_table[token].name = name;
rtas_table[token].fn = fn;
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 51b272e190..d0cc06a05f 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -19,6 +19,7 @@
#include "hw/loader.h"
#include "hw/boards.h"
#include "hw/s390x/virtio-ccw.h"
+#include "hw/s390x/vfio-ccw.h"
#include "hw/s390x/css.h"
#include "hw/s390x/ebcdic.h"
#include "ipl.h"
@@ -303,16 +304,36 @@ static void s390_ipl_set_boot_menu(S390IPLState *ipl)
ipl->qipl.boot_menu_timeout = cpu_to_be32(splash_time);
}
-static CcwDevice *s390_get_ccw_device(DeviceState *dev_st)
+#define CCW_DEVTYPE_NONE 0x00
+#define CCW_DEVTYPE_VIRTIO 0x01
+#define CCW_DEVTYPE_VIRTIO_NET 0x02
+#define CCW_DEVTYPE_SCSI 0x03
+#define CCW_DEVTYPE_VFIO 0x04
+
+static CcwDevice *s390_get_ccw_device(DeviceState *dev_st, int *devtype)
{
CcwDevice *ccw_dev = NULL;
+ int tmp_dt = CCW_DEVTYPE_NONE;
if (dev_st) {
+ VirtIONet *virtio_net_dev = (VirtIONet *)
+ object_dynamic_cast(OBJECT(dev_st), TYPE_VIRTIO_NET);
VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *)
object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent),
TYPE_VIRTIO_CCW_DEVICE);
+ VFIOCCWDevice *vfio_ccw_dev = (VFIOCCWDevice *)
+ object_dynamic_cast(OBJECT(dev_st), TYPE_VFIO_CCW);
+
if (virtio_ccw_dev) {
ccw_dev = CCW_DEVICE(virtio_ccw_dev);
+ if (virtio_net_dev) {
+ tmp_dt = CCW_DEVTYPE_VIRTIO_NET;
+ } else {
+ tmp_dt = CCW_DEVTYPE_VIRTIO;
+ }
+ } else if (vfio_ccw_dev) {
+ ccw_dev = CCW_DEVICE(vfio_ccw_dev);
+ tmp_dt = CCW_DEVTYPE_VFIO;
} else {
SCSIDevice *sd = (SCSIDevice *)
object_dynamic_cast(OBJECT(dev_st),
@@ -325,9 +346,13 @@ static CcwDevice *s390_get_ccw_device(DeviceState *dev_st)
ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw),
TYPE_CCW_DEVICE);
+ tmp_dt = CCW_DEVTYPE_SCSI;
}
}
}
+ if (devtype) {
+ *devtype = tmp_dt;
+ }
return ccw_dev;
}
@@ -335,20 +360,22 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
{
DeviceState *dev_st;
CcwDevice *ccw_dev = NULL;
+ SCSIDevice *sd;
+ int devtype;
dev_st = get_boot_device(0);
if (dev_st) {
- ccw_dev = s390_get_ccw_device(dev_st);
+ ccw_dev = s390_get_ccw_device(dev_st, &devtype);
}
/*
* Currently allow IPL only from CCW devices.
*/
if (ccw_dev) {
- SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
- TYPE_SCSI_DEVICE);
-
- if (sd) {
+ switch (devtype) {
+ case CCW_DEVTYPE_SCSI:
+ sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
+ TYPE_SCSI_DEVICE);
ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
ipl->iplb.blk0_len =
cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN);
@@ -358,20 +385,24 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
ipl->iplb.scsi.channel = cpu_to_be16(sd->channel);
ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
- } else {
- VirtIONet *vn = (VirtIONet *) object_dynamic_cast(OBJECT(dev_st),
- TYPE_VIRTIO_NET);
-
+ break;
+ case CCW_DEVTYPE_VFIO:
+ ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
+ ipl->iplb.pbt = S390_IPL_TYPE_CCW;
+ ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
+ ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
+ break;
+ case CCW_DEVTYPE_VIRTIO_NET:
+ ipl->netboot = true;
+ /* Fall through to CCW_DEVTYPE_VIRTIO case */
+ case CCW_DEVTYPE_VIRTIO:
ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
ipl->iplb.blk0_len =
cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN);
ipl->iplb.pbt = S390_IPL_TYPE_CCW;
ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
-
- if (vn) {
- ipl->netboot = true;
- }
+ break;
}
if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) {
@@ -530,7 +561,7 @@ void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type)
!ipl->netboot &&
ipl->iplb.pbt == S390_IPL_TYPE_CCW &&
is_virtio_scsi_device(&ipl->iplb)) {
- CcwDevice *ccw_dev = s390_get_ccw_device(get_boot_device(0));
+ CcwDevice *ccw_dev = s390_get_ccw_device(get_boot_device(0), NULL);
if (ccw_dev &&
cpu_to_be16(ccw_dev->sch->devno) == ipl->iplb.ccw.devno &&
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
index cad91ee626..f5f025d1b6 100644
--- a/hw/s390x/s390-ccw.c
+++ b/hw/s390x/s390-ccw.c
@@ -124,6 +124,14 @@ static void s390_ccw_unrealize(S390CCWDevice *cdev, Error **errp)
g_free(cdev->mdevid);
}
+static void s390_ccw_instance_init(Object *obj)
+{
+ S390CCWDevice *dev = S390_CCW_DEVICE(obj);
+
+ device_add_bootindex_property(obj, &dev->bootindex, "bootindex",
+ "/disk@0,0", DEVICE(obj), NULL);
+}
+
static void s390_ccw_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -137,6 +145,7 @@ static void s390_ccw_class_init(ObjectClass *klass, void *data)
static const TypeInfo s390_ccw_info = {
.name = TYPE_S390_CCW,
.parent = TYPE_CCW_DEVICE,
+ .instance_init = s390_ccw_instance_init,
.instance_size = sizeof(S390CCWDevice),
.class_size = sizeof(S390CCWDeviceClass),
.class_init = s390_ccw_class_init,
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index d11069b860..bbc6e8fa0b 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -15,6 +15,7 @@
#include "cpu.h"
#include "hw/boards.h"
#include "exec/address-spaces.h"
+#include "exec/ram_addr.h"
#include "hw/s390x/s390-virtio-hcall.h"
#include "hw/s390x/sclp.h"
#include "hw/s390x/s390_flic.h"
@@ -163,6 +164,7 @@ static void s390_memory_init(ram_addr_t mem_size)
MemoryRegion *sysmem = get_system_memory();
ram_addr_t chunk, offset = 0;
unsigned int number = 0;
+ Error *local_err = NULL;
gchar *name;
/* allocate RAM for core */
@@ -182,6 +184,15 @@ static void s390_memory_init(ram_addr_t mem_size)
}
g_free(name);
+ /*
+ * Configure the maximum page size. As no memory devices were created
+ * yet, this is the page size of initial memory only.
+ */
+ s390_set_max_pagesize(qemu_maxrampagesize(), &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ exit(EXIT_FAILURE);
+ }
/* Initialize storage key device */
s390_skeys_init();
/* Initialize storage attributes device */
@@ -253,6 +264,7 @@ static void ccw_init(MachineState *machine)
DeviceState *dev;
s390_sclp_init();
+ /* init memory + setup max page size. Required for the CPU model */
s390_memory_init(machine->ram_size);
/* init CPUs (incl. CPU model) early so s390_has_feature() works */
@@ -646,14 +658,26 @@ bool css_migration_enabled(void)
} \
type_init(ccw_machine_register_##suffix)
+static void ccw_machine_4_1_instance_options(MachineState *machine)
+{
+}
+
+static void ccw_machine_4_1_class_options(MachineClass *mc)
+{
+}
+DEFINE_CCW_MACHINE(4_1, "4.1", true);
+
static void ccw_machine_4_0_instance_options(MachineState *machine)
{
+ ccw_machine_4_1_instance_options(machine);
}
static void ccw_machine_4_0_class_options(MachineClass *mc)
{
+ ccw_machine_4_1_class_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_4_0, hw_compat_4_0_len);
}
-DEFINE_CCW_MACHINE(4_0, "4.0", true);
+DEFINE_CCW_MACHINE(4_0, "4.0", false);
static void ccw_machine_3_1_instance_options(MachineState *machine)
{
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index c44d13cc50..31dd3a2a87 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -21,12 +21,12 @@
#include "hw/vfio/vfio.h"
#include "hw/vfio/vfio-common.h"
#include "hw/s390x/s390-ccw.h"
+#include "hw/s390x/vfio-ccw.h"
#include "hw/s390x/ccw-device.h"
#include "exec/address-spaces.h"
#include "qemu/error-report.h"
-#define TYPE_VFIO_CCW "vfio-ccw"
-typedef struct VFIOCCWDevice {
+struct VFIOCCWDevice {
S390CCWDevice cdev;
VFIODevice vdev;
uint64_t io_region_size;
@@ -35,7 +35,7 @@ typedef struct VFIOCCWDevice {
EventNotifier io_notifier;
bool force_orb_pfch;
bool warned_orb_pfch;
-} VFIOCCWDevice;
+};
static inline void warn_once_pfch(VFIOCCWDevice *vcdev, SubchDev *sch,
const char *msg)
diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c
index 40a12001f5..29b2697fe1 100644
--- a/hw/vfio/pci-quirks.c
+++ b/hw/vfio/pci-quirks.c
@@ -2180,3 +2180,134 @@ int vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp)
return 0;
}
+
+static void vfio_pci_nvlink2_get_tgt(Object *obj, Visitor *v,
+ const char *name,
+ void *opaque, Error **errp)
+{
+ uint64_t tgt = (uintptr_t) opaque;
+ visit_type_uint64(v, name, &tgt, errp);
+}
+
+static void vfio_pci_nvlink2_get_link_speed(Object *obj, Visitor *v,
+ const char *name,
+ void *opaque, Error **errp)
+{
+ uint32_t link_speed = (uint32_t)(uintptr_t) opaque;
+ visit_type_uint32(v, name, &link_speed, errp);
+}
+
+int vfio_pci_nvidia_v100_ram_init(VFIOPCIDevice *vdev, Error **errp)
+{
+ int ret;
+ void *p;
+ struct vfio_region_info *nv2reg = NULL;
+ struct vfio_info_cap_header *hdr;
+ struct vfio_region_info_cap_nvlink2_ssatgt *cap;
+ VFIOQuirk *quirk;
+
+ ret = vfio_get_dev_region_info(&vdev->vbasedev,
+ VFIO_REGION_TYPE_PCI_VENDOR_TYPE |
+ PCI_VENDOR_ID_NVIDIA,
+ VFIO_REGION_SUBTYPE_NVIDIA_NVLINK2_RAM,
+ &nv2reg);
+ if (ret) {
+ return ret;
+ }
+
+ hdr = vfio_get_region_info_cap(nv2reg, VFIO_REGION_INFO_CAP_NVLINK2_SSATGT);
+ if (!hdr) {
+ ret = -ENODEV;
+ goto free_exit;
+ }
+ cap = (void *) hdr;
+
+ p = mmap(NULL, nv2reg->size, PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_SHARED, vdev->vbasedev.fd, nv2reg->offset);
+ if (p == MAP_FAILED) {
+ ret = -errno;
+ goto free_exit;
+ }
+
+ quirk = vfio_quirk_alloc(1);
+ memory_region_init_ram_ptr(&quirk->mem[0], OBJECT(vdev), "nvlink2-mr",
+ nv2reg->size, p);
+ QLIST_INSERT_HEAD(&vdev->bars[0].quirks, quirk, next);
+
+ object_property_add(OBJECT(vdev), "nvlink2-tgt", "uint64",
+ vfio_pci_nvlink2_get_tgt, NULL, NULL,
+ (void *) (uintptr_t) cap->tgt, NULL);
+ trace_vfio_pci_nvidia_gpu_setup_quirk(vdev->vbasedev.name, cap->tgt,
+ nv2reg->size);
+free_exit:
+ g_free(nv2reg);
+
+ return ret;
+}
+
+int vfio_pci_nvlink2_init(VFIOPCIDevice *vdev, Error **errp)
+{
+ int ret;
+ void *p;
+ struct vfio_region_info *atsdreg = NULL;
+ struct vfio_info_cap_header *hdr;
+ struct vfio_region_info_cap_nvlink2_ssatgt *captgt;
+ struct vfio_region_info_cap_nvlink2_lnkspd *capspeed;
+ VFIOQuirk *quirk;
+
+ ret = vfio_get_dev_region_info(&vdev->vbasedev,
+ VFIO_REGION_TYPE_PCI_VENDOR_TYPE |
+ PCI_VENDOR_ID_IBM,
+ VFIO_REGION_SUBTYPE_IBM_NVLINK2_ATSD,
+ &atsdreg);
+ if (ret) {
+ return ret;
+ }
+
+ hdr = vfio_get_region_info_cap(atsdreg,
+ VFIO_REGION_INFO_CAP_NVLINK2_SSATGT);
+ if (!hdr) {
+ ret = -ENODEV;
+ goto free_exit;
+ }
+ captgt = (void *) hdr;
+
+ hdr = vfio_get_region_info_cap(atsdreg,
+ VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD);
+ if (!hdr) {
+ ret = -ENODEV;
+ goto free_exit;
+ }
+ capspeed = (void *) hdr;
+
+ /* Some NVLink bridges may not have assigned ATSD */
+ if (atsdreg->size) {
+ p = mmap(NULL, atsdreg->size, PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_SHARED, vdev->vbasedev.fd, atsdreg->offset);
+ if (p == MAP_FAILED) {
+ ret = -errno;
+ goto free_exit;
+ }
+
+ quirk = vfio_quirk_alloc(1);
+ memory_region_init_ram_device_ptr(&quirk->mem[0], OBJECT(vdev),
+ "nvlink2-atsd-mr", atsdreg->size, p);
+ QLIST_INSERT_HEAD(&vdev->bars[0].quirks, quirk, next);
+ }
+
+ object_property_add(OBJECT(vdev), "nvlink2-tgt", "uint64",
+ vfio_pci_nvlink2_get_tgt, NULL, NULL,
+ (void *) (uintptr_t) captgt->tgt, NULL);
+ trace_vfio_pci_nvlink2_setup_quirk_ssatgt(vdev->vbasedev.name, captgt->tgt,
+ atsdreg->size);
+
+ object_property_add(OBJECT(vdev), "nvlink2-link-speed", "uint32",
+ vfio_pci_nvlink2_get_link_speed, NULL, NULL,
+ (void *) (uintptr_t) capspeed->link_speed, NULL);
+ trace_vfio_pci_nvlink2_setup_quirk_lnkspd(vdev->vbasedev.name,
+ capspeed->link_speed);
+free_exit:
+ g_free(atsdreg);
+
+ return ret;
+}
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 0142819ea6..8cecb53d5c 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -3086,6 +3086,20 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
}
}
+ if (vdev->vendor_id == PCI_VENDOR_ID_NVIDIA) {
+ ret = vfio_pci_nvidia_v100_ram_init(vdev, errp);
+ if (ret && ret != -ENODEV) {
+ error_report("Failed to setup NVIDIA V100 GPU RAM");
+ }
+ }
+
+ if (vdev->vendor_id == PCI_VENDOR_ID_IBM) {
+ ret = vfio_pci_nvlink2_init(vdev, errp);
+ if (ret && ret != -ENODEV) {
+ error_report("Failed to setup NVlink2 bridge");
+ }
+ }
+
vfio_register_err_notifier(vdev);
vfio_register_req_notifier(vdev);
vfio_setup_resetfn_quirk(vdev);
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index c11c3f1670..cfcd1a81b8 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -196,6 +196,8 @@ int vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp);
int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev,
struct vfio_region_info *info,
Error **errp);
+int vfio_pci_nvidia_v100_ram_init(VFIOPCIDevice *vdev, Error **errp);
+int vfio_pci_nvlink2_init(VFIOPCIDevice *vdev, Error **errp);
void vfio_display_reset(VFIOPCIDevice *vdev);
int vfio_display_probe(VFIOPCIDevice *vdev, Error **errp);
diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c
index 57fe758e54..96c0ad9d9b 100644
--- a/hw/vfio/spapr.c
+++ b/hw/vfio/spapr.c
@@ -148,7 +148,7 @@ int vfio_spapr_create_window(VFIOContainer *container,
uint64_t pagesize = memory_region_iommu_get_min_page_size(iommu_mr);
unsigned entries, bits_total, bits_per_level, max_levels;
struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) };
- long rampagesize = qemu_getrampagesize();
+ long rampagesize = qemu_minrampagesize();
/*
* The host might not support the guest supported IOMMU page size,
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index eb589930a5..b1ef55a33f 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -86,6 +86,10 @@ vfio_pci_igd_opregion_enabled(const char *name) "%s"
vfio_pci_igd_host_bridge_enabled(const char *name) "%s"
vfio_pci_igd_lpc_bridge_enabled(const char *name) "%s"
+vfio_pci_nvidia_gpu_setup_quirk(const char *name, uint64_t tgt, uint64_t size) "%s tgt=0x%"PRIx64" size=0x%"PRIx64
+vfio_pci_nvlink2_setup_quirk_ssatgt(const char *name, uint64_t tgt, uint64_t size) "%s tgt=0x%"PRIx64" size=0x%"PRIx64
+vfio_pci_nvlink2_setup_quirk_lnkspd(const char *name, uint32_t link_speed) "%s link_speed=0x%x"
+
# common.c
vfio_region_write(const char *name, int index, uint64_t addr, uint64_t data, unsigned size) " (%s:region%d+0x%"PRIx64", 0x%"PRIx64 ", %d)"
vfio_region_read(char *name, int index, uint64_t addr, unsigned size, uint64_t data) " (%s:region%d+0x%"PRIx64", %d) = 0x%"PRIx64
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index 9ecd911c3e..139ad79390 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -73,7 +73,8 @@ static inline unsigned long int ramblock_recv_bitmap_offset(void *host_addr,
bool ramblock_is_pmem(RAMBlock *rb);
-long qemu_getrampagesize(void);
+long qemu_minrampagesize(void);
+long qemu_maxrampagesize(void);
/**
* qemu_ram_alloc_from_file,
diff --git a/include/hw/boards.h b/include/hw/boards.h
index e231860666..6f7916f88f 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -57,7 +57,6 @@ void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
#define MACHINE_CLASS(klass) \
OBJECT_CLASS_CHECK(MachineClass, (klass), TYPE_MACHINE)
-MachineClass *find_default_machine(void);
extern MachineState *current_machine;
void machine_run_board_init(MachineState *machine);
@@ -293,6 +292,9 @@ struct MachineState {
} \
type_init(machine_initfn##_register_types)
+extern GlobalProperty hw_compat_4_0[];
+extern const size_t hw_compat_4_0_len;
+
extern GlobalProperty hw_compat_3_1[];
extern const size_t hw_compat_3_1_len;
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index ca65ef18af..43df7230a2 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -293,6 +293,9 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
int e820_get_num_entries(void);
bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
+extern GlobalProperty pc_compat_4_0[];
+extern const size_t pc_compat_4_0_len;
+
extern GlobalProperty pc_compat_3_1[];
extern const size_t pc_compat_3_1_len;
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index b4aad26798..53519c835e 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -87,6 +87,9 @@ struct SpaprPhbState {
uint32_t mig_liobn;
hwaddr mig_mem_win_addr, mig_mem_win_size;
hwaddr mig_io_win_addr, mig_io_win_size;
+ hwaddr nv2_gpa_win_addr;
+ hwaddr nv2_atsd_win_addr;
+ struct spapr_phb_pci_nvgpu_config *nvgpus;
};
#define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
@@ -105,6 +108,22 @@ struct SpaprPhbState {
#define SPAPR_PCI_MSI_WINDOW 0x40000000000ULL
+#define SPAPR_PCI_NV2RAM64_WIN_BASE SPAPR_PCI_LIMIT
+#define SPAPR_PCI_NV2RAM64_WIN_SIZE (2 * TiB) /* For up to 6 GPUs 256GB each */
+
+/* Max number of these GPUsper a physical box */
+#define NVGPU_MAX_NUM 6
+/* Max number of NVLinks per GPU in any physical box */
+#define NVGPU_MAX_LINKS 3
+
+/*
+ * GPU RAM starts at 64TiB so huge DMA window to cover it all ends at 128TiB
+ * which is enough. We do not need DMA for ATSD so we put them at 128TiB.
+ */
+#define SPAPR_PCI_NV2ATSD_WIN_BASE (128 * TiB)
+#define SPAPR_PCI_NV2ATSD_WIN_SIZE (NVGPU_MAX_NUM * NVGPU_MAX_LINKS * \
+ 64 * KiB)
+
static inline qemu_irq spapr_phb_lsi_qirq(struct SpaprPhbState *phb, int pin)
{
SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
@@ -135,6 +154,13 @@ int spapr_phb_vfio_eeh_get_state(SpaprPhbState *sphb, int *state);
int spapr_phb_vfio_eeh_reset(SpaprPhbState *sphb, int option);
int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb);
void spapr_phb_vfio_reset(DeviceState *qdev);
+void spapr_phb_nvgpu_setup(SpaprPhbState *sphb, Error **errp);
+void spapr_phb_nvgpu_free(SpaprPhbState *sphb);
+void spapr_phb_nvgpu_populate_dt(SpaprPhbState *sphb, void *fdt, int bus_off,
+ Error **errp);
+void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb, void *fdt);
+void spapr_phb_nvgpu_populate_pcidev_dt(PCIDevice *dev, void *fdt, int offset,
+ SpaprPhbState *sphb);
#else
static inline bool spapr_phb_eeh_available(SpaprPhbState *sphb)
{
@@ -161,6 +187,25 @@ static inline int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb)
static inline void spapr_phb_vfio_reset(DeviceState *qdev)
{
}
+static inline void spapr_phb_nvgpu_setup(SpaprPhbState *sphb, Error **errp)
+{
+}
+static inline void spapr_phb_nvgpu_free(SpaprPhbState *sphb)
+{
+}
+static inline void spapr_phb_nvgpu_populate_dt(SpaprPhbState *sphb, void *fdt,
+ int bus_off, Error **errp)
+{
+}
+static inline void spapr_phb_nvgpu_ram_populate_dt(SpaprPhbState *sphb,
+ void *fdt)
+{
+}
+static inline void spapr_phb_nvgpu_populate_pcidev_dt(PCIDevice *dev, void *fdt,
+ int offset,
+ SpaprPhbState *sphb)
+{
+}
#endif
void spapr_phb_dma_reset(SpaprPhbState *sphb);
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 0abb06b357..fdd4c43d3a 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -413,6 +413,10 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void pci_bus_irqs_cleanup(PCIBus *bus);
int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
+static inline int pci_swizzle(int slot, int pin)
+{
+ return (slot + pin) % PCI_NUM_PINS;
+}
int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
PCIBus *pci_register_root_bus(DeviceState *parent, const char *name,
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 5ea8081041..7e32f309c2 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -123,7 +123,8 @@ struct SpaprMachineClass {
void (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
uint64_t *buid, hwaddr *pio,
hwaddr *mmio32, hwaddr *mmio64,
- unsigned n_dma, uint32_t *liobns, Error **errp);
+ unsigned n_dma, uint32_t *liobns, hwaddr *nv2gpa,
+ hwaddr *nv2atsd, Error **errp);
SpaprResizeHpt resize_hpt_default;
SpaprCapabilities default_caps;
SpaprIrq *irq;
@@ -199,6 +200,8 @@ struct SpaprMachineState {
bool cmd_line_caps[SPAPR_CAP_NUM];
SpaprCapabilities def, eff, mig;
+
+ unsigned gpu_numa_id;
};
#define H_SUCCESS 0
@@ -672,6 +675,10 @@ typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, SpaprMachineState *sm,
uint32_t nargs, target_ulong args,
uint32_t nret, target_ulong rets);
void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn);
+static inline void spapr_rtas_unregister(int token)
+{
+ spapr_rtas_register(token, NULL, NULL);
+}
target_ulong spapr_rtas_call(PowerPCCPU *cpu, SpaprMachineState *sm,
uint32_t token, uint32_t nargs, target_ulong args,
uint32_t nret, target_ulong rets);
@@ -777,6 +784,8 @@ void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift,
Error **errp);
void spapr_clear_pending_events(SpaprMachineState *spapr);
int spapr_max_server_number(SpaprMachineState *spapr);
+void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
+ uint64_t pte0, uint64_t pte1);
/* DRC callbacks. */
void spapr_core_release(DeviceState *dev);
diff --git a/include/hw/s390x/s390-ccw.h b/include/hw/s390x/s390-ccw.h
index 7d15a1a5d4..901d805d79 100644
--- a/include/hw/s390x/s390-ccw.h
+++ b/include/hw/s390x/s390-ccw.h
@@ -27,6 +27,7 @@ typedef struct S390CCWDevice {
CcwDevice parent_obj;
CssDevId hostid;
char *mdevid;
+ int32_t bootindex;
} S390CCWDevice;
typedef struct S390CCWDeviceClass {
diff --git a/include/hw/s390x/vfio-ccw.h b/include/hw/s390x/vfio-ccw.h
new file mode 100644
index 0000000000..ee5250d0d7
--- /dev/null
+++ b/include/hw/s390x/vfio-ccw.h
@@ -0,0 +1,28 @@
+/*
+ * vfio based subchannel assignment support
+ *
+ * Copyright 2017, 2019 IBM Corp.
+ * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
+ * Xiao Feng Ren <renxiaof@linux.vnet.ibm.com>
+ * Pierre Morel <pmorel@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef HW_VFIO_CCW_H
+#define HW_VFIO_CCW_H
+
+#include "hw/vfio/vfio-common.h"
+#include "hw/s390x/s390-ccw.h"
+#include "hw/s390x/ccw-device.h"
+
+#define TYPE_VFIO_CCW "vfio-ccw"
+#define VFIO_CCW(obj) \
+ OBJECT_CHECK(VFIOCCWDevice, (obj), TYPE_VFIO_CCW)
+
+#define TYPE_VFIO_CCW "vfio-ccw"
+typedef struct VFIOCCWDevice VFIOCCWDevice;
+
+#endif
diff --git a/include/qemu/mmap-alloc.h b/include/qemu/mmap-alloc.h
index ef04f0ed5b..eec98d82c1 100644
--- a/include/qemu/mmap-alloc.h
+++ b/include/qemu/mmap-alloc.h
@@ -7,7 +7,26 @@ size_t qemu_fd_getpagesize(int fd);
size_t qemu_mempath_getpagesize(const char *mem_path);
-void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared);
+/**
+ * qemu_ram_mmap: mmap the specified file or device.
+ *
+ * Parameters:
+ * @fd: the file or the device to mmap
+ * @size: the number of bytes to be mmaped
+ * @align: if not zero, specify the alignment of the starting mapping address;
+ * otherwise, the alignment in use will be determined by QEMU.
+ * @shared: map has RAM_SHARED flag.
+ * @is_pmem: map has RAM_PMEM flag.
+ *
+ * Return:
+ * On success, return a pointer to the mapped area.
+ * On failure, return MAP_FAILED.
+ */
+void *qemu_ram_mmap(int fd,
+ size_t size,
+ size_t align,
+ bool shared,
+ bool is_pmem);
void qemu_ram_munmap(int fd, void *ptr, size_t size);
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index e9bec3a5bc..08abcbd3fe 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -681,15 +681,15 @@ ObjectClass *cpu_class_by_name(const char *typename, const char *cpu_model);
CPUState *cpu_create(const char *typename);
/**
- * parse_cpu_model:
- * @cpu_model: The model string including optional parameters.
+ * parse_cpu_option:
+ * @cpu_option: The -cpu option including optional parameters.
*
* processes optional parameters and registers them as global properties
*
* Returns: type of CPU to create or prints error and terminates process
* if an error occurred.
*/
-const char *parse_cpu_model(const char *cpu_model);
+const char *parse_cpu_option(const char *cpu_option);
/**
* cpu_has_work:
diff --git a/linux-headers/asm-arm/mman.h b/linux-headers/asm-arm/mman.h
new file mode 100644
index 0000000000..41f99c573b
--- /dev/null
+++ b/linux-headers/asm-arm/mman.h
@@ -0,0 +1,4 @@
+#include <asm-generic/mman.h>
+
+#define arch_mmap_check(addr, len, flags) \
+ (((flags) & MAP_FIXED && (addr) < FIRST_USER_ADDRESS) ? -EINVAL : 0)
diff --git a/linux-headers/asm-arm64/mman.h b/linux-headers/asm-arm64/mman.h
new file mode 100644
index 0000000000..8eebf89f5a
--- /dev/null
+++ b/linux-headers/asm-arm64/mman.h
@@ -0,0 +1 @@
+#include <asm-generic/mman.h>
diff --git a/linux-headers/asm-generic/hugetlb_encode.h b/linux-headers/asm-generic/hugetlb_encode.h
new file mode 100644
index 0000000000..b0f8e87235
--- /dev/null
+++ b/linux-headers/asm-generic/hugetlb_encode.h
@@ -0,0 +1,36 @@
+#ifndef _ASM_GENERIC_HUGETLB_ENCODE_H_
+#define _ASM_GENERIC_HUGETLB_ENCODE_H_
+
+/*
+ * Several system calls take a flag to request "hugetlb" huge pages.
+ * Without further specification, these system calls will use the
+ * system's default huge page size. If a system supports multiple
+ * huge page sizes, the desired huge page size can be specified in
+ * bits [26:31] of the flag arguments. The value in these 6 bits
+ * will encode the log2 of the huge page size.
+ *
+ * The following definitions are associated with this huge page size
+ * encoding in flag arguments. System call specific header files
+ * that use this encoding should include this file. They can then
+ * provide definitions based on these with their own specific prefix.
+ * for example:
+ * #define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
+ */
+
+#define HUGETLB_FLAG_ENCODE_SHIFT 26
+#define HUGETLB_FLAG_ENCODE_MASK 0x3f
+
+#define HUGETLB_FLAG_ENCODE_64KB (16 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_512KB (19 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_1MB (20 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_2MB (21 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_8MB (23 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_16MB (24 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_32MB (25 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_256MB (28 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_512MB (29 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_1GB (30 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_2GB (31 << HUGETLB_FLAG_ENCODE_SHIFT)
+#define HUGETLB_FLAG_ENCODE_16GB (34 << HUGETLB_FLAG_ENCODE_SHIFT)
+
+#endif /* _ASM_GENERIC_HUGETLB_ENCODE_H_ */
diff --git a/linux-headers/asm-generic/mman-common.h b/linux-headers/asm-generic/mman-common.h
new file mode 100644
index 0000000000..e7ee32861d
--- /dev/null
+++ b/linux-headers/asm-generic/mman-common.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __ASM_GENERIC_MMAN_COMMON_H
+#define __ASM_GENERIC_MMAN_COMMON_H
+
+/*
+ Author: Michael S. Tsirkin <mst@mellanox.co.il>, Mellanox Technologies Ltd.
+ Based on: asm-xxx/mman.h
+*/
+
+#define PROT_READ 0x1 /* page can be read */
+#define PROT_WRITE 0x2 /* page can be written */
+#define PROT_EXEC 0x4 /* page can be executed */
+#define PROT_SEM 0x8 /* page may be used for atomic ops */
+#define PROT_NONE 0x0 /* page can not be accessed */
+#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
+#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
+
+#define MAP_SHARED 0x01 /* Share changes */
+#define MAP_PRIVATE 0x02 /* Changes are private */
+#define MAP_SHARED_VALIDATE 0x03 /* share + validate extension flags */
+#define MAP_TYPE 0x0f /* Mask for type of mapping */
+#define MAP_FIXED 0x10 /* Interpret addr exactly */
+#define MAP_ANONYMOUS 0x20 /* don't use a file */
+#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
+# define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be uninitialized */
+#else
+# define MAP_UNINITIALIZED 0x0 /* Don't support this flag */
+#endif
+
+/* 0x0100 - 0x80000 flags are defined in asm-generic/mman.h */
+#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
+
+/*
+ * Flags for mlock
+ */
+#define MLOCK_ONFAULT 0x01 /* Lock pages in range after they are faulted in, do not prefault */
+
+#define MS_ASYNC 1 /* sync memory asynchronously */
+#define MS_INVALIDATE 2 /* invalidate the caches */
+#define MS_SYNC 4 /* synchronous memory sync */
+
+#define MADV_NORMAL 0 /* no further special treatment */
+#define MADV_RANDOM 1 /* expect random page references */
+#define MADV_SEQUENTIAL 2 /* expect sequential page references */
+#define MADV_WILLNEED 3 /* will need these pages */
+#define MADV_DONTNEED 4 /* don't need these pages */
+
+/* common parameters: try to keep these consistent across architectures */
+#define MADV_FREE 8 /* free pages only if memory pressure */
+#define MADV_REMOVE 9 /* remove these pages & resources */
+#define MADV_DONTFORK 10 /* don't inherit across fork */
+#define MADV_DOFORK 11 /* do inherit across fork */
+#define MADV_HWPOISON 100 /* poison a page for testing */
+#define MADV_SOFT_OFFLINE 101 /* soft offline page for testing */
+
+#define MADV_MERGEABLE 12 /* KSM may merge identical pages */
+#define MADV_UNMERGEABLE 13 /* KSM may not merge identical pages */
+
+#define MADV_HUGEPAGE 14 /* Worth backing with hugepages */
+#define MADV_NOHUGEPAGE 15 /* Not worth backing with hugepages */
+
+#define MADV_DONTDUMP 16 /* Explicity exclude from the core dump,
+ overrides the coredump filter bits */
+#define MADV_DODUMP 17 /* Clear the MADV_DONTDUMP flag */
+
+#define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */
+#define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */
+
+/* compatibility flags */
+#define MAP_FILE 0
+
+#define PKEY_DISABLE_ACCESS 0x1
+#define PKEY_DISABLE_WRITE 0x2
+#define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS |\
+ PKEY_DISABLE_WRITE)
+
+#endif /* __ASM_GENERIC_MMAN_COMMON_H */
diff --git a/linux-headers/asm-generic/mman.h b/linux-headers/asm-generic/mman.h
new file mode 100644
index 0000000000..653687d977
--- /dev/null
+++ b/linux-headers/asm-generic/mman.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __ASM_GENERIC_MMAN_H
+#define __ASM_GENERIC_MMAN_H
+
+#include <asm-generic/mman-common.h>
+
+#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
+#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
+#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
+#define MAP_LOCKED 0x2000 /* pages are locked */
+#define MAP_NORESERVE 0x4000 /* don't check for reservations */
+#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
+#define MAP_NONBLOCK 0x10000 /* do not block on IO */
+#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
+#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
+#define MAP_SYNC 0x80000 /* perform synchronous page faults for the mapping */
+
+/* Bits [26:31] are reserved, see mman-common.h for MAP_HUGETLB usage */
+
+#define MCL_CURRENT 1 /* lock all current mappings */
+#define MCL_FUTURE 2 /* lock all future mappings */
+#define MCL_ONFAULT 4 /* lock all pages that are faulted in */
+
+#endif /* __ASM_GENERIC_MMAN_H */
diff --git a/linux-headers/asm-mips/mman.h b/linux-headers/asm-mips/mman.h
new file mode 100644
index 0000000000..3035ca499c
--- /dev/null
+++ b/linux-headers/asm-mips/mman.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1999, 2002 by Ralf Baechle
+ */
+#ifndef _ASM_MMAN_H
+#define _ASM_MMAN_H
+
+/*
+ * Protections are chosen from these bits, OR'd together. The
+ * implementation does not necessarily support PROT_EXEC or PROT_WRITE
+ * without PROT_READ. The only guarantees are that no writing will be
+ * allowed without PROT_WRITE and no access will be allowed for PROT_NONE.
+ */
+#define PROT_NONE 0x00 /* page can not be accessed */
+#define PROT_READ 0x01 /* page can be read */
+#define PROT_WRITE 0x02 /* page can be written */
+#define PROT_EXEC 0x04 /* page can be executed */
+/* 0x08 reserved for PROT_EXEC_NOFLUSH */
+#define PROT_SEM 0x10 /* page may be used for atomic ops */
+#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
+#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
+
+/*
+ * Flags for mmap
+ */
+#define MAP_SHARED 0x001 /* Share changes */
+#define MAP_PRIVATE 0x002 /* Changes are private */
+#define MAP_SHARED_VALIDATE 0x003 /* share + validate extension flags */
+#define MAP_TYPE 0x00f /* Mask for type of mapping */
+#define MAP_FIXED 0x010 /* Interpret addr exactly */
+
+/* not used by linux, but here to make sure we don't clash with ABI defines */
+#define MAP_RENAME 0x020 /* Assign page to file */
+#define MAP_AUTOGROW 0x040 /* File may grow by writing */
+#define MAP_LOCAL 0x080 /* Copy on fork/sproc */
+#define MAP_AUTORSRV 0x100 /* Logical swap reserved on demand */
+
+/* These are linux-specific */
+#define MAP_NORESERVE 0x0400 /* don't check for reservations */
+#define MAP_ANONYMOUS 0x0800 /* don't use a file */
+#define MAP_GROWSDOWN 0x1000 /* stack-like segment */
+#define MAP_DENYWRITE 0x2000 /* ETXTBSY */
+#define MAP_EXECUTABLE 0x4000 /* mark it as an executable */
+#define MAP_LOCKED 0x8000 /* pages are locked */
+#define MAP_POPULATE 0x10000 /* populate (prefault) pagetables */
+#define MAP_NONBLOCK 0x20000 /* do not block on IO */
+#define MAP_STACK 0x40000 /* give out an address that is best suited for process/thread stacks */
+#define MAP_HUGETLB 0x80000 /* create a huge page mapping */
+#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
+
+/*
+ * Flags for msync
+ */
+#define MS_ASYNC 0x0001 /* sync memory asynchronously */
+#define MS_INVALIDATE 0x0002 /* invalidate mappings & caches */
+#define MS_SYNC 0x0004 /* synchronous memory sync */
+
+/*
+ * Flags for mlockall
+ */
+#define MCL_CURRENT 1 /* lock all current mappings */
+#define MCL_FUTURE 2 /* lock all future mappings */
+#define MCL_ONFAULT 4 /* lock all pages that are faulted in */
+
+/*
+ * Flags for mlock
+ */
+#define MLOCK_ONFAULT 0x01 /* Lock pages in range after they are faulted in, do not prefault */
+
+#define MADV_NORMAL 0 /* no further special treatment */
+#define MADV_RANDOM 1 /* expect random page references */
+#define MADV_SEQUENTIAL 2 /* expect sequential page references */
+#define MADV_WILLNEED 3 /* will need these pages */
+#define MADV_DONTNEED 4 /* don't need these pages */
+
+/* common parameters: try to keep these consistent across architectures */
+#define MADV_FREE 8 /* free pages only if memory pressure */
+#define MADV_REMOVE 9 /* remove these pages & resources */
+#define MADV_DONTFORK 10 /* don't inherit across fork */
+#define MADV_DOFORK 11 /* do inherit across fork */
+
+#define MADV_MERGEABLE 12 /* KSM may merge identical pages */
+#define MADV_UNMERGEABLE 13 /* KSM may not merge identical pages */
+#define MADV_HWPOISON 100 /* poison a page for testing */
+
+#define MADV_HUGEPAGE 14 /* Worth backing with hugepages */
+#define MADV_NOHUGEPAGE 15 /* Not worth backing with hugepages */
+
+#define MADV_DONTDUMP 16 /* Explicity exclude from the core dump,
+ overrides the coredump filter bits */
+#define MADV_DODUMP 17 /* Clear the MADV_NODUMP flag */
+
+#define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */
+#define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */
+
+/* compatibility flags */
+#define MAP_FILE 0
+
+#define PKEY_DISABLE_ACCESS 0x1
+#define PKEY_DISABLE_WRITE 0x2
+#define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS |\
+ PKEY_DISABLE_WRITE)
+
+#endif /* _ASM_MMAN_H */
diff --git a/linux-headers/asm-powerpc/mman.h b/linux-headers/asm-powerpc/mman.h
new file mode 100644
index 0000000000..1c2b3fca05
--- /dev/null
+++ b/linux-headers/asm-powerpc/mman.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _ASM_POWERPC_MMAN_H
+#define _ASM_POWERPC_MMAN_H
+
+#include <asm-generic/mman-common.h>
+
+
+#define PROT_SAO 0x10 /* Strong Access Ordering */
+
+#define MAP_RENAME MAP_ANONYMOUS /* In SunOS terminology */
+#define MAP_NORESERVE 0x40 /* don't reserve swap pages */
+#define MAP_LOCKED 0x80
+
+#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
+#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
+#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
+
+#define MCL_CURRENT 0x2000 /* lock all currently mapped pages */
+#define MCL_FUTURE 0x4000 /* lock all additions to address space */
+#define MCL_ONFAULT 0x8000 /* lock all pages that are faulted in */
+
+#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
+#define MAP_NONBLOCK 0x10000 /* do not block on IO */
+#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
+#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
+
+/* Override any generic PKEY permission defines */
+#define PKEY_DISABLE_EXECUTE 0x4
+#undef PKEY_ACCESS_MASK
+#define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS |\
+ PKEY_DISABLE_WRITE |\
+ PKEY_DISABLE_EXECUTE)
+#endif /* _ASM_POWERPC_MMAN_H */
diff --git a/linux-headers/asm-s390/mman.h b/linux-headers/asm-s390/mman.h
new file mode 100644
index 0000000000..8eebf89f5a
--- /dev/null
+++ b/linux-headers/asm-s390/mman.h
@@ -0,0 +1 @@
+#include <asm-generic/mman.h>
diff --git a/linux-headers/asm-x86/mman.h b/linux-headers/asm-x86/mman.h
new file mode 100644
index 0000000000..d4a8d0424b
--- /dev/null
+++ b/linux-headers/asm-x86/mman.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _ASM_X86_MMAN_H
+#define _ASM_X86_MMAN_H
+
+#define MAP_32BIT 0x40 /* only give out 32bit addresses */
+
+#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
+/*
+ * Take the 4 protection key bits out of the vma->vm_flags
+ * value and turn them in to the bits that we can put in
+ * to a pte.
+ *
+ * Only override these if Protection Keys are available
+ * (which is only on 64-bit).
+ */
+#define arch_vm_get_page_prot(vm_flags) __pgprot( \
+ ((vm_flags) & VM_PKEY_BIT0 ? _PAGE_PKEY_BIT0 : 0) | \
+ ((vm_flags) & VM_PKEY_BIT1 ? _PAGE_PKEY_BIT1 : 0) | \
+ ((vm_flags) & VM_PKEY_BIT2 ? _PAGE_PKEY_BIT2 : 0) | \
+ ((vm_flags) & VM_PKEY_BIT3 ? _PAGE_PKEY_BIT3 : 0))
+
+#define arch_calc_vm_prot_bits(prot, key) ( \
+ ((key) & 0x1 ? VM_PKEY_BIT0 : 0) | \
+ ((key) & 0x2 ? VM_PKEY_BIT1 : 0) | \
+ ((key) & 0x4 ? VM_PKEY_BIT2 : 0) | \
+ ((key) & 0x8 ? VM_PKEY_BIT3 : 0))
+#endif
+
+#include <asm-generic/mman.h>
+
+#endif /* _ASM_X86_MMAN_H */
diff --git a/linux-headers/linux/mman.h b/linux-headers/linux/mman.h
new file mode 100644
index 0000000000..3c44b6f480
--- /dev/null
+++ b/linux-headers/linux/mman.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_MMAN_H
+#define _LINUX_MMAN_H
+
+#include <asm/mman.h>
+#include <asm-generic/hugetlb_encode.h>
+
+#define MREMAP_MAYMOVE 1
+#define MREMAP_FIXED 2
+
+#define OVERCOMMIT_GUESS 0
+#define OVERCOMMIT_ALWAYS 1
+#define OVERCOMMIT_NEVER 2
+
+/*
+ * Huge page size encoding when MAP_HUGETLB is specified, and a huge page
+ * size other than the default is desired. See hugetlb_encode.h.
+ * All known huge page size encodings are provided here. It is the
+ * responsibility of the application to know which sizes are supported on
+ * the running system. See mmap(2) man page for details.
+ */
+#define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
+#define MAP_HUGE_MASK HUGETLB_FLAG_ENCODE_MASK
+
+#define MAP_HUGE_64KB HUGETLB_FLAG_ENCODE_64KB
+#define MAP_HUGE_512KB HUGETLB_FLAG_ENCODE_512KB
+#define MAP_HUGE_1MB HUGETLB_FLAG_ENCODE_1MB
+#define MAP_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB
+#define MAP_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB
+#define MAP_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB
+#define MAP_HUGE_32MB HUGETLB_FLAG_ENCODE_32MB
+#define MAP_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB
+#define MAP_HUGE_512MB HUGETLB_FLAG_ENCODE_512MB
+#define MAP_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB
+#define MAP_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB
+#define MAP_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB
+
+#endif /* _LINUX_MMAN_H */
diff --git a/linux-user/main.c b/linux-user/main.c
index 17387166ab..3d2230320b 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -662,7 +662,7 @@ int main(int argc, char **argv, char **envp)
if (cpu_model == NULL) {
cpu_model = cpu_get_model(get_elf_eflags(execfd));
}
- cpu_type = parse_cpu_model(cpu_model);
+ cpu_type = parse_cpu_option(cpu_model);
/* init tcg before creating CPUs and to get qemu_host_page_size */
tcg_exec_init(0);
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
index 450a076dc0..ba054828d3 100644
--- a/pc-bios/s390-ccw.img
+++ b/pc-bios/s390-ccw.img
Binary files differ
diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile
index 1eb316b02f..a048b6b077 100644
--- a/pc-bios/s390-ccw/Makefile
+++ b/pc-bios/s390-ccw/Makefile
@@ -10,7 +10,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
.PHONY : all clean build-all
OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \
- virtio.o virtio-scsi.o virtio-blkdev.o libc.o
+ virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o dasd-ipl.o
QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS))
QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float
diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c
new file mode 100644
index 0000000000..339ec5fbe7
--- /dev/null
+++ b/pc-bios/s390-ccw/cio.c
@@ -0,0 +1,423 @@
+/*
+ * S390 Channel I/O
+ *
+ * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
+ * Copyright (c) 2019 IBM Corp.
+ *
+ * Author(s): Jason J. Herne <jjherne@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "libc.h"
+#include "s390-ccw.h"
+#include "s390-arch.h"
+#include "helper.h"
+#include "cio.h"
+
+static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+
+static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb);
+
+int enable_mss_facility(void)
+{
+ int ret;
+ ChscAreaSda *sda_area = (ChscAreaSda *) chsc_page;
+
+ memset(sda_area, 0, PAGE_SIZE);
+ sda_area->request.length = 0x0400;
+ sda_area->request.code = 0x0031;
+ sda_area->operation_code = 0x2;
+
+ ret = chsc(sda_area);
+ if ((ret == 0) && (sda_area->response.code == 0x0001)) {
+ return 0;
+ }
+ return -EIO;
+}
+
+void enable_subchannel(SubChannelId schid)
+{
+ Schib schib;
+
+ stsch_err(schid, &schib);
+ schib.pmcw.ena = 1;
+ msch(schid, &schib);
+}
+
+uint16_t cu_type(SubChannelId schid)
+{
+ Ccw1 sense_id_ccw;
+ SenseId sense_data;
+
+ sense_id_ccw.cmd_code = CCW_CMD_SENSE_ID;
+ sense_id_ccw.cda = ptr2u32(&sense_data);
+ sense_id_ccw.count = sizeof(sense_data);
+ sense_id_ccw.flags |= CCW_FLAG_SLI;
+
+ if (do_cio(schid, CU_TYPE_UNKNOWN, ptr2u32(&sense_id_ccw), CCW_FMT1)) {
+ panic("Failed to run SenseID CCw\n");
+ }
+
+ return sense_data.cu_type;
+}
+
+int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data,
+ uint16_t data_size)
+{
+ Ccw1 senseCcw;
+ Irb irb;
+
+ senseCcw.cmd_code = CCW_CMD_BASIC_SENSE;
+ senseCcw.cda = ptr2u32(sense_data);
+ senseCcw.count = data_size;
+
+ return __do_cio(schid, ptr2u32(&senseCcw), CCW_FMT1, &irb);
+}
+
+static bool irb_error(Irb *irb)
+{
+ if (irb->scsw.cstat) {
+ return true;
+ }
+ return irb->scsw.dstat != (SCSW_DSTAT_DEVEND | SCSW_DSTAT_CHEND);
+}
+
+static void print_eckd_dasd_sense_data(SenseDataEckdDasd *sd)
+{
+ char msgline[512];
+
+ if (sd->config_info & 0x8000) {
+ sclp_print("Eckd Dasd Sense Data (fmt 24-bytes):\n");
+ } else {
+ sclp_print("Eckd Dasd Sense Data (fmt 32-bytes):\n");
+ }
+
+ strcat(msgline, " Sense Condition Flags :");
+ if (sd->common_status & SNS_STAT0_CMD_REJECT) {
+ strcat(msgline, " [Cmd-Reject]");
+ }
+ if (sd->common_status & SNS_STAT0_INTERVENTION_REQ) {
+ strcat(msgline, " [Intervention-Required]");
+ }
+ if (sd->common_status & SNS_STAT0_BUS_OUT_CHECK) {
+ strcat(msgline, " [Bus-Out-Parity-Check]");
+ }
+ if (sd->common_status & SNS_STAT0_EQUIPMENT_CHECK) {
+ strcat(msgline, " [Equipment-Check]");
+ }
+ if (sd->common_status & SNS_STAT0_DATA_CHECK) {
+ strcat(msgline, " [Data-Check]");
+ }
+ if (sd->common_status & SNS_STAT0_OVERRUN) {
+ strcat(msgline, " [Overrun]");
+ }
+ if (sd->common_status & SNS_STAT0_INCOMPL_DOMAIN) {
+ strcat(msgline, " [Incomplete-Domain]");
+ }
+
+ if (sd->status[0] & SNS_STAT1_PERM_ERR) {
+ strcat(msgline, " [Permanent-Error]");
+ }
+ if (sd->status[0] & SNS_STAT1_INV_TRACK_FORMAT) {
+ strcat(msgline, " [Invalid-Track-Fmt]");
+ }
+ if (sd->status[0] & SNS_STAT1_EOC) {
+ strcat(msgline, " [End-of-Cyl]");
+ }
+ if (sd->status[0] & SNS_STAT1_MESSAGE_TO_OPER) {
+ strcat(msgline, " [Operator-Msg]");
+ }
+ if (sd->status[0] & SNS_STAT1_NO_REC_FOUND) {
+ strcat(msgline, " [No-Record-Found]");
+ }
+ if (sd->status[0] & SNS_STAT1_FILE_PROTECTED) {
+ strcat(msgline, " [File-Protected]");
+ }
+ if (sd->status[0] & SNS_STAT1_WRITE_INHIBITED) {
+ strcat(msgline, " [Write-Inhibited]");
+ }
+ if (sd->status[0] & SNS_STAT1_IMPRECISE_END) {
+ strcat(msgline, " [Imprecise-Ending]");
+ }
+
+ if (sd->status[1] & SNS_STAT2_REQ_INH_WRITE) {
+ strcat(msgline, " [Req-Inhibit-Write]");
+ }
+ if (sd->status[1] & SNS_STAT2_CORRECTABLE) {
+ strcat(msgline, " [Correctable-Data-Check]");
+ }
+ if (sd->status[1] & SNS_STAT2_FIRST_LOG_ERR) {
+ strcat(msgline, " [First-Error-Log]");
+ }
+ if (sd->status[1] & SNS_STAT2_ENV_DATA_PRESENT) {
+ strcat(msgline, " [Env-Data-Present]");
+ }
+ if (sd->status[1] & SNS_STAT2_IMPRECISE_END) {
+ strcat(msgline, " [Imprecise-End]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ print_int(" Residual Count =", sd->res_count);
+ print_int(" Phys Drive ID =", sd->phys_drive_id);
+ print_int(" low cyl address =", sd->low_cyl_addr);
+ print_int(" head addr & hi cyl =", sd->head_high_cyl_addr);
+ print_int(" format/message =", sd->fmt_msg);
+ print_int(" fmt-dependent[0-7] =", sd->fmt_dependent_info[0]);
+ print_int(" fmt-dependent[8-15]=", sd->fmt_dependent_info[1]);
+ print_int(" prog action code =", sd->program_action_code);
+ print_int(" Configuration info =", sd->config_info);
+ print_int(" mcode / hi-cyl =", sd->mcode_hicyl);
+ print_int(" cyl & head addr [0]=", sd->cyl_head_addr[0]);
+ print_int(" cyl & head addr [1]=", sd->cyl_head_addr[1]);
+ print_int(" cyl & head addr [2]=", sd->cyl_head_addr[2]);
+}
+
+static void print_irb_err(Irb *irb)
+{
+ uint64_t this_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa);
+ uint64_t prev_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa - 8);
+ char msgline[256];
+
+ sclp_print("Interrupt Response Block Data:\n");
+
+ strcat(msgline, " Function Ctrl :");
+ if (irb->scsw.ctrl & SCSW_FCTL_START_FUNC) {
+ strcat(msgline, " [Start]");
+ }
+ if (irb->scsw.ctrl & SCSW_FCTL_HALT_FUNC) {
+ strcat(msgline, " [Halt]");
+ }
+ if (irb->scsw.ctrl & SCSW_FCTL_CLEAR_FUNC) {
+ strcat(msgline, " [Clear]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ msgline[0] = '\0';
+ strcat(msgline, " Activity Ctrl :");
+ if (irb->scsw.ctrl & SCSW_ACTL_RESUME_PEND) {
+ strcat(msgline, " [Resume-Pending]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_START_PEND) {
+ strcat(msgline, " [Start-Pending]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_HALT_PEND) {
+ strcat(msgline, " [Halt-Pending]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_CLEAR_PEND) {
+ strcat(msgline, " [Clear-Pending]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_CH_ACTIVE) {
+ strcat(msgline, " [Channel-Active]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_DEV_ACTIVE) {
+ strcat(msgline, " [Device-Active]");
+ }
+ if (irb->scsw.ctrl & SCSW_ACTL_SUSPENDED) {
+ strcat(msgline, " [Suspended]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ msgline[0] = '\0';
+ strcat(msgline, " Status Ctrl :");
+ if (irb->scsw.ctrl & SCSW_SCTL_ALERT) {
+ strcat(msgline, " [Alert]");
+ }
+ if (irb->scsw.ctrl & SCSW_SCTL_INTERMED) {
+ strcat(msgline, " [Intermediate]");
+ }
+ if (irb->scsw.ctrl & SCSW_SCTL_PRIMARY) {
+ strcat(msgline, " [Primary]");
+ }
+ if (irb->scsw.ctrl & SCSW_SCTL_SECONDARY) {
+ strcat(msgline, " [Secondary]");
+ }
+ if (irb->scsw.ctrl & SCSW_SCTL_STATUS_PEND) {
+ strcat(msgline, " [Status-Pending]");
+ }
+
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ msgline[0] = '\0';
+ strcat(msgline, " Device Status :");
+ if (irb->scsw.dstat & SCSW_DSTAT_ATTN) {
+ strcat(msgline, " [Attention]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_STATMOD) {
+ strcat(msgline, " [Status-Modifier]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_CUEND) {
+ strcat(msgline, " [Ctrl-Unit-End]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_BUSY) {
+ strcat(msgline, " [Busy]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_CHEND) {
+ strcat(msgline, " [Channel-End]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_DEVEND) {
+ strcat(msgline, " [Device-End]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_UCHK) {
+ strcat(msgline, " [Unit-Check]");
+ }
+ if (irb->scsw.dstat & SCSW_DSTAT_UEXCP) {
+ strcat(msgline, " [Unit-Exception]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ msgline[0] = '\0';
+ strcat(msgline, " Channel Status :");
+ if (irb->scsw.cstat & SCSW_CSTAT_PCINT) {
+ strcat(msgline, " [Program-Ctrl-Interruption]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_BADLEN) {
+ strcat(msgline, " [Incorrect-Length]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_PROGCHK) {
+ strcat(msgline, " [Program-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_PROTCHK) {
+ strcat(msgline, " [Protection-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_CHDCHK) {
+ strcat(msgline, " [Channel-Data-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_CHCCHK) {
+ strcat(msgline, " [Channel-Ctrl-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_ICCHK) {
+ strcat(msgline, " [Interface-Ctrl-Check]");
+ }
+ if (irb->scsw.cstat & SCSW_CSTAT_CHAINCHK) {
+ strcat(msgline, " [Chaining-Check]");
+ }
+ strcat(msgline, "\n");
+ sclp_print(msgline);
+
+ print_int(" cpa=", irb->scsw.cpa);
+ print_int(" prev_ccw=", prev_ccw);
+ print_int(" this_ccw=", this_ccw);
+}
+
+/*
+ * Handles executing ssch, tsch and returns the irb obtained from tsch.
+ * Returns 0 on success, -1 if unexpected status pending and we need to retry,
+ * otherwise returns condition code from ssch/tsch for error cases.
+ */
+static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb)
+{
+ CmdOrb orb = {};
+ int rc;
+
+ IPL_assert(fmt == 0 || fmt == 1, "Invalid ccw format");
+
+ /* ccw_addr must be <= 24 bits and point to at least one whole ccw. */
+ if (fmt == 0) {
+ IPL_assert(ccw_addr <= 0xFFFFFF - 8, "Invalid ccw address");
+ }
+
+ orb.fmt = fmt;
+ orb.pfch = 1; /* QEMU's cio implementation requires prefetch */
+ orb.c64 = 1; /* QEMU's cio implementation requires 64-bit idaws */
+ orb.lpm = 0xFF; /* All paths allowed */
+ orb.cpa = ccw_addr;
+
+ rc = ssch(schid, &orb);
+ if (rc == 1 || rc == 2) {
+ /* Subchannel status pending or busy. Eat status and ask for retry. */
+ tsch(schid, irb);
+ return -1;
+ }
+ if (rc) {
+ print_int("ssch failed with cc=", rc);
+ return rc;
+ }
+
+ consume_io_int();
+
+ /* collect status */
+ rc = tsch(schid, irb);
+ if (rc) {
+ print_int("tsch failed with cc=", rc);
+ }
+
+ return rc;
+}
+
+/*
+ * Executes a channel program at a given subchannel. The request to run the
+ * channel program is sent to the subchannel, we then wait for the interrupt
+ * signaling completion of the I/O operation(s) performed by the channel
+ * program. Lastly we verify that the i/o operation completed without error and
+ * that the interrupt we received was for the subchannel used to run the
+ * channel program.
+ *
+ * Note: This function assumes it is running in an environment where no other
+ * cpus are generating or receiving I/O interrupts. So either run it in a
+ * single-cpu environment or make sure all other cpus are not doing I/O and
+ * have I/O interrupts masked off. We also assume that only one device is
+ * active (generating i/o interrupts).
+ *
+ * Returns non-zero on error.
+ */
+int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt)
+{
+ Irb irb = {};
+ SenseDataEckdDasd sd;
+ int rc, retries = 0;
+
+ while (true) {
+ rc = __do_cio(schid, ccw_addr, fmt, &irb);
+
+ if (rc == -1) {
+ retries++;
+ continue;
+ }
+ if (rc) {
+ /* ssch/tsch error. Message already reported by __do_cio */
+ break;
+ }
+
+ if (!irb_error(&irb)) {
+ break;
+ }
+
+ /*
+ * Unexpected unit check, or interface-control-check. Use sense to
+ * clear (unit check only) then retry.
+ */
+ if ((unit_check(&irb) || iface_ctrl_check(&irb)) && retries <= 2) {
+ if (unit_check(&irb)) {
+ basic_sense(schid, cutype, &sd, sizeof(sd));
+ }
+ retries++;
+ continue;
+ }
+
+ sclp_print("cio device error\n");
+ print_int(" ssid ", schid.ssid);
+ print_int(" cssid ", schid.cssid);
+ print_int(" sch_no", schid.sch_no);
+ print_int(" ctrl-unit type", cutype);
+ sclp_print("\n");
+ print_irb_err(&irb);
+ if (cutype == CU_TYPE_DASD_3990 || cutype == CU_TYPE_DASD_2107 ||
+ cutype == CU_TYPE_UNKNOWN) {
+ if (!basic_sense(schid, cutype, &sd, sizeof(sd))) {
+ print_eckd_dasd_sense_data(&sd);
+ }
+ }
+ rc = -1;
+ break;
+ }
+
+ return rc;
+}
diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h
index 1a0795f645..aaa432dedd 100644
--- a/pc-bios/s390-ccw/cio.h
+++ b/pc-bios/s390-ccw/cio.h
@@ -17,35 +17,35 @@
* path management control word
*/
struct pmcw {
- __u32 intparm; /* interruption parameter */
- __u32 qf : 1; /* qdio facility */
- __u32 w : 1;
- __u32 isc : 3; /* interruption sublass */
- __u32 res5 : 3; /* reserved zeros */
- __u32 ena : 1; /* enabled */
- __u32 lm : 2; /* limit mode */
- __u32 mme : 2; /* measurement-mode enable */
- __u32 mp : 1; /* multipath mode */
- __u32 tf : 1; /* timing facility */
- __u32 dnv : 1; /* device number valid */
- __u32 dev : 16; /* device number */
- __u8 lpm; /* logical path mask */
- __u8 pnom; /* path not operational mask */
- __u8 lpum; /* last path used mask */
- __u8 pim; /* path installed mask */
- __u16 mbi; /* measurement-block index */
- __u8 pom; /* path operational mask */
- __u8 pam; /* path available mask */
- __u8 chpid[8]; /* CHPID 0-7 (if available) */
- __u32 unused1 : 8; /* reserved zeros */
- __u32 st : 3; /* subchannel type */
- __u32 unused2 : 18; /* reserved zeros */
- __u32 mbfc : 1; /* measurement block format control */
- __u32 xmwme : 1; /* extended measurement word mode enable */
- __u32 csense : 1; /* concurrent sense; can be enabled ...*/
- /* ... per MSCH, however, if facility */
- /* ... is not installed, this results */
- /* ... in an operand exception. */
+ __u32 intparm; /* interruption parameter */
+ __u32 qf:1; /* qdio facility */
+ __u32 w:1;
+ __u32 isc:3; /* interruption sublass */
+ __u32 res5:3; /* reserved zeros */
+ __u32 ena:1; /* enabled */
+ __u32 lm:2; /* limit mode */
+ __u32 mme:2; /* measurement-mode enable */
+ __u32 mp:1; /* multipath mode */
+ __u32 tf:1; /* timing facility */
+ __u32 dnv:1; /* device number valid */
+ __u32 dev:16; /* device number */
+ __u8 lpm; /* logical path mask */
+ __u8 pnom; /* path not operational mask */
+ __u8 lpum; /* last path used mask */
+ __u8 pim; /* path installed mask */
+ __u16 mbi; /* measurement-block index */
+ __u8 pom; /* path operational mask */
+ __u8 pam; /* path available mask */
+ __u8 chpid[8]; /* CHPID 0-7 (if available) */
+ __u32 unused1:8; /* reserved zeros */
+ __u32 st:3; /* subchannel type */
+ __u32 unused2:18; /* reserved zeros */
+ __u32 mbfc:1; /* measurement block format control */
+ __u32 xmwme:1; /* extended measurement word mode enable */
+ __u32 csense:1; /* concurrent sense; can be enabled ...*/
+ /* ... per MSCH, however, if facility */
+ /* ... is not installed, this results */
+ /* ... in an operand exception. */
} __attribute__ ((packed));
/* Target SCHIB configuration. */
@@ -70,35 +70,72 @@ struct scsw {
__u16 count;
} __attribute__ ((packed));
-#define SCSW_FCTL_CLEAR_FUNC 0x1000
-#define SCSW_FCTL_HALT_FUNC 0x2000
+/* Function Control */
#define SCSW_FCTL_START_FUNC 0x4000
+#define SCSW_FCTL_HALT_FUNC 0x2000
+#define SCSW_FCTL_CLEAR_FUNC 0x1000
+
+/* Activity Control */
+#define SCSW_ACTL_RESUME_PEND 0x0800
+#define SCSW_ACTL_START_PEND 0x0400
+#define SCSW_ACTL_HALT_PEND 0x0200
+#define SCSW_ACTL_CLEAR_PEND 0x0100
+#define SCSW_ACTL_CH_ACTIVE 0x0080
+#define SCSW_ACTL_DEV_ACTIVE 0x0040
+#define SCSW_ACTL_SUSPENDED 0x0020
+
+/* Status Control */
+#define SCSW_SCTL_ALERT 0x0010
+#define SCSW_SCTL_INTERMED 0x0008
+#define SCSW_SCTL_PRIMARY 0x0004
+#define SCSW_SCTL_SECONDARY 0x0002
+#define SCSW_SCTL_STATUS_PEND 0x0001
+
+/* SCSW Device Status Flags */
+#define SCSW_DSTAT_ATTN 0x80
+#define SCSW_DSTAT_STATMOD 0x40
+#define SCSW_DSTAT_CUEND 0x20
+#define SCSW_DSTAT_BUSY 0x10
+#define SCSW_DSTAT_CHEND 0x08
+#define SCSW_DSTAT_DEVEND 0x04
+#define SCSW_DSTAT_UCHK 0x02
+#define SCSW_DSTAT_UEXCP 0x01
+
+/* SCSW Subchannel Status Flags */
+#define SCSW_CSTAT_PCINT 0x80
+#define SCSW_CSTAT_BADLEN 0x40
+#define SCSW_CSTAT_PROGCHK 0x20
+#define SCSW_CSTAT_PROTCHK 0x10
+#define SCSW_CSTAT_CHDCHK 0x08
+#define SCSW_CSTAT_CHCCHK 0x04
+#define SCSW_CSTAT_ICCHK 0x02
+#define SCSW_CSTAT_CHAINCHK 0x01
/*
* subchannel information block
*/
-struct schib {
+typedef struct schib {
struct pmcw pmcw; /* path management control word */
struct scsw scsw; /* subchannel status word */
__u64 mba; /* measurement block address */
__u8 mda[4]; /* model dependent area */
-} __attribute__ ((packed,aligned(4)));
-
-struct subchannel_id {
- __u32 cssid : 8;
- __u32 : 4;
- __u32 m : 1;
- __u32 ssid : 2;
- __u32 one : 1;
- __u32 sch_no : 16;
-} __attribute__ ((packed, aligned(4)));
+} __attribute__ ((packed, aligned(4))) Schib;
+
+typedef struct subchannel_id {
+ __u32 cssid:8;
+ __u32:4;
+ __u32 m:1;
+ __u32 ssid:2;
+ __u32 one:1;
+ __u32 sch_no:16;
+} __attribute__ ((packed, aligned(4))) SubChannelId;
struct chsc_header {
__u16 length;
__u16 code;
} __attribute__((packed));
-struct chsc_area_sda {
+typedef struct chsc_area_sda {
struct chsc_header request;
__u8 reserved1:4;
__u8 format:4;
@@ -111,29 +148,49 @@ struct chsc_area_sda {
__u32 reserved5:4;
__u32 format2:4;
__u32 reserved6:24;
-} __attribute__((packed));
+} __attribute__((packed)) ChscAreaSda;
/*
* TPI info structure
*/
struct tpi_info {
struct subchannel_id schid;
- __u32 intparm; /* interruption parameter */
- __u32 adapter_IO : 1;
- __u32 reserved2 : 1;
- __u32 isc : 3;
- __u32 reserved3 : 12;
- __u32 int_type : 3;
- __u32 reserved4 : 12;
+ __u32 intparm; /* interruption parameter */
+ __u32 adapter_IO:1;
+ __u32 reserved2:1;
+ __u32 isc:3;
+ __u32 reserved3:12;
+ __u32 int_type:3;
+ __u32 reserved4:12;
} __attribute__ ((packed, aligned(4)));
-/* channel command word (type 1) */
-struct ccw1 {
+/* channel command word (format 0) */
+typedef struct ccw0 {
+ __u8 cmd_code;
+ __u32 cda:24;
+ __u32 chainData:1;
+ __u32 chain:1;
+ __u32 sli:1;
+ __u32 skip:1;
+ __u32 pci:1;
+ __u32 ida:1;
+ __u32 suspend:1;
+ __u32 mida:1;
+ __u8 reserved;
+ __u16 count;
+} __attribute__ ((packed, aligned(8))) Ccw0;
+
+/* channel command word (format 1) */
+typedef struct ccw1 {
__u8 cmd_code;
__u8 flags;
__u16 count;
__u32 cda;
-} __attribute__ ((packed, aligned(8)));
+} __attribute__ ((packed, aligned(8))) Ccw1;
+
+/* do_cio() CCW formats */
+#define CCW_FMT0 0x00
+#define CCW_FMT1 0x01
#define CCW_FLAG_DC 0x80
#define CCW_FLAG_CC 0x40
@@ -143,11 +200,14 @@ struct ccw1 {
#define CCW_FLAG_IDA 0x04
#define CCW_FLAG_SUSPEND 0x02
+/* Common CCW commands */
+#define CCW_CMD_READ_IPL 0x02
#define CCW_CMD_NOOP 0x03
#define CCW_CMD_BASIC_SENSE 0x04
#define CCW_CMD_TIC 0x08
#define CCW_CMD_SENSE_ID 0xe4
+/* Virtio CCW commands */
#define CCW_CMD_SET_VQ 0x13
#define CCW_CMD_VDEV_RESET 0x33
#define CCW_CMD_READ_FEAT 0x12
@@ -159,10 +219,16 @@ struct ccw1 {
#define CCW_CMD_SET_CONF_IND 0x53
#define CCW_CMD_READ_VQ_CONF 0x32
+/* DASD CCW commands */
+#define CCW_CMD_DASD_READ 0x06
+#define CCW_CMD_DASD_SEEK 0x07
+#define CCW_CMD_DASD_SEARCH_ID_EQ 0x31
+#define CCW_CMD_DASD_READ_MT 0x86
+
/*
* Command-mode operation request block
*/
-struct cmd_orb {
+typedef struct cmd_orb {
__u32 intparm; /* interruption parameter */
__u32 key:4; /* flags, like key, suspend control, etc. */
__u32 spnd:1; /* suspend control */
@@ -182,7 +248,7 @@ struct cmd_orb {
__u32 zero:6; /* reserved zeros */
__u32 orbx:1; /* ORB extension control */
__u32 cpa; /* channel program address */
-} __attribute__ ((packed, aligned(4)));
+} __attribute__ ((packed, aligned(4))) CmdOrb;
struct ciw {
__u8 type;
@@ -190,10 +256,15 @@ struct ciw {
__u16 count;
};
+#define CU_TYPE_UNKNOWN 0x0000
+#define CU_TYPE_DASD_2107 0x2107
+#define CU_TYPE_VIRTIO 0x3832
+#define CU_TYPE_DASD_3990 0x3990
+
/*
* sense-id response buffer layout
*/
-struct senseid {
+typedef struct senseid {
/* common part */
__u8 reserved; /* always 0x'FF' */
__u16 cu_type; /* control unit type */
@@ -203,15 +274,94 @@ struct senseid {
__u8 unused; /* padding byte */
/* extended part */
struct ciw ciw[62];
-} __attribute__ ((packed, aligned(4)));
+} __attribute__ ((packed, aligned(4))) SenseId;
+
+/*
+ * architected values for first sense byte - common_status. Bits 0-5 of this
+ * field are common to all device types.
+ */
+#define SNS_STAT0_CMD_REJECT 0x80
+#define SNS_STAT0_INTERVENTION_REQ 0x40
+#define SNS_STAT0_BUS_OUT_CHECK 0x20
+#define SNS_STAT0_EQUIPMENT_CHECK 0x10
+#define SNS_STAT0_DATA_CHECK 0x08
+#define SNS_STAT0_OVERRUN 0x04
+#define SNS_STAT0_INCOMPL_DOMAIN 0x01
+
+/* ECKD DASD status[0] byte */
+#define SNS_STAT1_PERM_ERR 0x80
+#define SNS_STAT1_INV_TRACK_FORMAT 0x40
+#define SNS_STAT1_EOC 0x20
+#define SNS_STAT1_MESSAGE_TO_OPER 0x10
+#define SNS_STAT1_NO_REC_FOUND 0x08
+#define SNS_STAT1_FILE_PROTECTED 0x04
+#define SNS_STAT1_WRITE_INHIBITED 0x02
+#define SNS_STAT1_IMPRECISE_END 0x01
+
+/* ECKD DASD status[1] byte */
+#define SNS_STAT2_REQ_INH_WRITE 0x80
+#define SNS_STAT2_CORRECTABLE 0x40
+#define SNS_STAT2_FIRST_LOG_ERR 0x20
+#define SNS_STAT2_ENV_DATA_PRESENT 0x10
+#define SNS_STAT2_IMPRECISE_END 0x04
+
+/* ECKD DASD 24-byte Sense fmt_msg codes */
+#define SENSE24_FMT_PROG_SYS 0x0
+#define SENSE24_FMT_EQUIPMENT 0x2
+#define SENSE24_FMT_CONTROLLER 0x3
+#define SENSE24_FMT_MISC 0xF
+
+/* basic sense response buffer layout */
+typedef struct SenseDataEckdDasd {
+ uint8_t common_status;
+ uint8_t status[2];
+ uint8_t res_count;
+ uint8_t phys_drive_id;
+ uint8_t low_cyl_addr;
+ uint8_t head_high_cyl_addr;
+ uint8_t fmt_msg;
+ uint64_t fmt_dependent_info[2];
+ uint8_t reserved;
+ uint8_t program_action_code;
+ uint16_t config_info;
+ uint8_t mcode_hicyl;
+ uint8_t cyl_head_addr[3];
+} __attribute__ ((packed, aligned(4))) SenseDataEckdDasd;
+
+#define ECKD_SENSE24_GET_FMT(sd) (sd->fmt_msg & 0xF0 >> 4)
+#define ECKD_SENSE24_GET_MSG(sd) (sd->fmt_msg & 0x0F)
+
+#define unit_check(irb) ((irb)->scsw.dstat & SCSW_DSTAT_UCHK)
+#define iface_ctrl_check(irb) ((irb)->scsw.cstat & SCSW_CSTAT_ICCHK)
/* interruption response block */
-struct irb {
+typedef struct irb {
struct scsw scsw;
__u32 esw[5];
__u32 ecw[8];
__u32 emw[8];
-} __attribute__ ((packed, aligned(4)));
+} __attribute__ ((packed, aligned(4))) Irb;
+
+/* Used for SEEK ccw commands */
+typedef struct CcwSeekData {
+ uint16_t reserved;
+ uint16_t cyl;
+ uint16_t head;
+} __attribute__((packed)) CcwSeekData;
+
+/* Used for SEARCH ID ccw commands */
+typedef struct CcwSearchIdData {
+ uint16_t cyl;
+ uint16_t head;
+ uint8_t record;
+} __attribute__((packed)) CcwSearchIdData;
+
+int enable_mss_facility(void);
+void enable_subchannel(SubChannelId schid);
+uint16_t cu_type(SubChannelId schid);
+int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data,
+ uint16_t data_size);
+int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt);
/*
* Some S390 specific IO instructions as inline
diff --git a/pc-bios/s390-ccw/dasd-ipl.c b/pc-bios/s390-ccw/dasd-ipl.c
new file mode 100644
index 0000000000..0fc879bb8e
--- /dev/null
+++ b/pc-bios/s390-ccw/dasd-ipl.c
@@ -0,0 +1,235 @@
+/*
+ * S390 IPL (boot) from a real DASD device via vfio framework.
+ *
+ * Copyright (c) 2019 Jason J. Herne <jjherne@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#include "libc.h"
+#include "s390-ccw.h"
+#include "s390-arch.h"
+#include "dasd-ipl.h"
+#include "helper.h"
+
+static char prefix_page[PAGE_SIZE * 2]
+ __attribute__((__aligned__(PAGE_SIZE * 2)));
+
+static void enable_prefixing(void)
+{
+ memcpy(&prefix_page, lowcore, 4096);
+ set_prefix(ptr2u32(&prefix_page));
+}
+
+static void disable_prefixing(void)
+{
+ set_prefix(0);
+ /* Copy io interrupt info back to low core */
+ memcpy((void *)&lowcore->subchannel_id, prefix_page + 0xB8, 12);
+}
+
+static bool is_read_tic_ccw_chain(Ccw0 *ccw)
+{
+ Ccw0 *next_ccw = ccw + 1;
+
+ return ((ccw->cmd_code == CCW_CMD_DASD_READ ||
+ ccw->cmd_code == CCW_CMD_DASD_READ_MT) &&
+ ccw->chain && next_ccw->cmd_code == CCW_CMD_TIC);
+}
+
+static bool dynamic_cp_fixup(uint32_t ccw_addr, uint32_t *next_cpa)
+{
+ Ccw0 *cur_ccw = (Ccw0 *)(uint64_t)ccw_addr;
+ Ccw0 *tic_ccw;
+
+ while (true) {
+ /* Skip over inline TIC (it might not have the chain bit on) */
+ if (cur_ccw->cmd_code == CCW_CMD_TIC &&
+ cur_ccw->cda == ptr2u32(cur_ccw) - 8) {
+ cur_ccw += 1;
+ continue;
+ }
+
+ if (!cur_ccw->chain) {
+ break;
+ }
+ if (is_read_tic_ccw_chain(cur_ccw)) {
+ /*
+ * Breaking a chain of CCWs may alter the semantics or even the
+ * validity of a channel program. The heuristic implemented below
+ * seems to work well in practice for the channel programs
+ * generated by zipl.
+ */
+ tic_ccw = cur_ccw + 1;
+ *next_cpa = tic_ccw->cda;
+ cur_ccw->chain = 0;
+ return true;
+ }
+ cur_ccw += 1;
+ }
+ return false;
+}
+
+static int run_dynamic_ccw_program(SubChannelId schid, uint16_t cutype,
+ uint32_t cpa)
+{
+ bool has_next;
+ uint32_t next_cpa = 0;
+ int rc;
+
+ do {
+ has_next = dynamic_cp_fixup(cpa, &next_cpa);
+
+ print_int("executing ccw chain at ", cpa);
+ enable_prefixing();
+ rc = do_cio(schid, cutype, cpa, CCW_FMT0);
+ disable_prefixing();
+
+ if (rc) {
+ break;
+ }
+ cpa = next_cpa;
+ } while (has_next);
+
+ return rc;
+}
+
+static void make_readipl(void)
+{
+ Ccw0 *ccwIplRead = (Ccw0 *)0x00;
+
+ /* Create Read IPL ccw at address 0 */
+ ccwIplRead->cmd_code = CCW_CMD_READ_IPL;
+ ccwIplRead->cda = 0x00; /* Read into address 0x00 in main memory */
+ ccwIplRead->chain = 0; /* Chain flag */
+ ccwIplRead->count = 0x18; /* Read 0x18 bytes of data */
+}
+
+static void run_readipl(SubChannelId schid, uint16_t cutype)
+{
+ if (do_cio(schid, cutype, 0x00, CCW_FMT0)) {
+ panic("dasd-ipl: Failed to run Read IPL channel program\n");
+ }
+}
+
+/*
+ * The architecture states that IPL1 data should consist of a psw followed by
+ * format-0 READ and TIC CCWs. Let's sanity check.
+ */
+static void check_ipl1(void)
+{
+ Ccw0 *ccwread = (Ccw0 *)0x08;
+ Ccw0 *ccwtic = (Ccw0 *)0x10;
+
+ if (ccwread->cmd_code != CCW_CMD_DASD_READ ||
+ ccwtic->cmd_code != CCW_CMD_TIC) {
+ panic("dasd-ipl: IPL1 data invalid. Is this disk really bootable?\n");
+ }
+}
+
+static void check_ipl2(uint32_t ipl2_addr)
+{
+ Ccw0 *ccw = u32toptr(ipl2_addr);
+
+ if (ipl2_addr == 0x00) {
+ panic("IPL2 address invalid. Is this disk really bootable?\n");
+ }
+ if (ccw->cmd_code == 0x00) {
+ panic("IPL2 ccw data invalid. Is this disk really bootable?\n");
+ }
+}
+
+static uint32_t read_ipl2_addr(void)
+{
+ Ccw0 *ccwtic = (Ccw0 *)0x10;
+
+ return ccwtic->cda;
+}
+
+static void ipl1_fixup(void)
+{
+ Ccw0 *ccwSeek = (Ccw0 *) 0x08;
+ Ccw0 *ccwSearchID = (Ccw0 *) 0x10;
+ Ccw0 *ccwSearchTic = (Ccw0 *) 0x18;
+ Ccw0 *ccwRead = (Ccw0 *) 0x20;
+ CcwSeekData *seekData = (CcwSeekData *) 0x30;
+ CcwSearchIdData *searchData = (CcwSearchIdData *) 0x38;
+
+ /* move IPL1 CCWs to make room for CCWs needed to locate record 2 */
+ memcpy(ccwRead, (void *)0x08, 16);
+
+ /* Disable chaining so we don't TIC to IPL2 channel program */
+ ccwRead->chain = 0x00;
+
+ ccwSeek->cmd_code = CCW_CMD_DASD_SEEK;
+ ccwSeek->cda = ptr2u32(seekData);
+ ccwSeek->chain = 1;
+ ccwSeek->count = sizeof(*seekData);
+ seekData->reserved = 0x00;
+ seekData->cyl = 0x00;
+ seekData->head = 0x00;
+
+ ccwSearchID->cmd_code = CCW_CMD_DASD_SEARCH_ID_EQ;
+ ccwSearchID->cda = ptr2u32(searchData);
+ ccwSearchID->chain = 1;
+ ccwSearchID->count = sizeof(*searchData);
+ searchData->cyl = 0;
+ searchData->head = 0;
+ searchData->record = 2;
+
+ /* Go back to Search CCW if correct record not yet found */
+ ccwSearchTic->cmd_code = CCW_CMD_TIC;
+ ccwSearchTic->cda = ptr2u32(ccwSearchID);
+}
+
+static void run_ipl1(SubChannelId schid, uint16_t cutype)
+ {
+ uint32_t startAddr = 0x08;
+
+ if (do_cio(schid, cutype, startAddr, CCW_FMT0)) {
+ panic("dasd-ipl: Failed to run IPL1 channel program\n");
+ }
+}
+
+static void run_ipl2(SubChannelId schid, uint16_t cutype, uint32_t addr)
+{
+ if (run_dynamic_ccw_program(schid, cutype, addr)) {
+ panic("dasd-ipl: Failed to run IPL2 channel program\n");
+ }
+}
+
+/*
+ * Limitations in vfio-ccw support complicate the IPL process. Details can
+ * be found in docs/devel/s390-dasd-ipl.txt
+ */
+void dasd_ipl(SubChannelId schid, uint16_t cutype)
+{
+ PSWLegacy *pswl = (PSWLegacy *) 0x00;
+ uint32_t ipl2_addr;
+
+ /* Construct Read IPL CCW and run it to read IPL1 from boot disk */
+ make_readipl();
+ run_readipl(schid, cutype);
+ ipl2_addr = read_ipl2_addr();
+ check_ipl1();
+
+ /*
+ * Fixup IPL1 channel program to account for vfio-ccw limitations, then run
+ * it to read IPL2 channel program from boot disk.
+ */
+ ipl1_fixup();
+ run_ipl1(schid, cutype);
+ check_ipl2(ipl2_addr);
+
+ /*
+ * Run IPL2 channel program to read operating system code from boot disk
+ */
+ run_ipl2(schid, cutype, ipl2_addr);
+
+ /* Transfer control to the guest operating system */
+ pswl->mask |= PSW_MASK_EAMODE; /* Force z-mode */
+ pswl->addr |= PSW_MASK_BAMODE; /* ... */
+ jump_to_low_kernel();
+}
diff --git a/pc-bios/s390-ccw/dasd-ipl.h b/pc-bios/s390-ccw/dasd-ipl.h
new file mode 100644
index 0000000000..c394828906
--- /dev/null
+++ b/pc-bios/s390-ccw/dasd-ipl.h
@@ -0,0 +1,16 @@
+/*
+ * S390 IPL (boot) from a real DASD device via vfio framework.
+ *
+ * Copyright (c) 2019 Jason J. Herne <jjherne@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef DASD_IPL_H
+#define DASD_IPL_H
+
+void dasd_ipl(SubChannelId schid, uint16_t cutype);
+
+#endif /* DASD_IPL_H */
diff --git a/pc-bios/s390-ccw/helper.h b/pc-bios/s390-ccw/helper.h
new file mode 100644
index 0000000000..78d5bc7442
--- /dev/null
+++ b/pc-bios/s390-ccw/helper.h
@@ -0,0 +1,31 @@
+/*
+ * Helper Functions
+ *
+ * Copyright (c) 2019 IBM Corp.
+ *
+ * Author(s): Jason J. Herne <jjherne@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef S390_CCW_HELPER_H
+#define S390_CCW_HELPER_H
+
+#include "s390-ccw.h"
+
+/* Avoids compiler warnings when casting a pointer to a u32 */
+static inline uint32_t ptr2u32(void *ptr)
+{
+ IPL_assert((uint64_t)ptr <= 0xffffffff, "ptr2u32: ptr too large");
+ return (uint32_t)(uint64_t)ptr;
+}
+
+/* Avoids compiler warnings when casting a u32 to a pointer */
+static inline void *u32toptr(uint32_t n)
+{
+ return (void *)(uint64_t)n;
+}
+
+#endif
diff --git a/pc-bios/s390-ccw/libc.h b/pc-bios/s390-ccw/libc.h
index 818517ff5d..bcdc45732d 100644
--- a/pc-bios/s390-ccw/libc.h
+++ b/pc-bios/s390-ccw/libc.h
@@ -67,6 +67,17 @@ static inline size_t strlen(const char *str)
return i;
}
+static inline char *strcat(char *dest, const char *src)
+{
+ int i;
+ char *dest_end = dest + strlen(dest);
+
+ for (i = 0; i <= strlen(src); i++) {
+ dest_end[i] = src[i];
+ }
+ return dest;
+}
+
static inline int isdigit(int c)
{
return (c >= '0') && (c <= '9');
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index 544851d672..a69c73349e 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -9,21 +9,27 @@
*/
#include "libc.h"
+#include "s390-arch.h"
#include "s390-ccw.h"
+#include "cio.h"
#include "virtio.h"
+#include "dasd-ipl.h"
char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
static SubChannelId blk_schid = { .one = 1 };
-IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
QemuIplParameters qipl;
+IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
+static bool have_iplb;
+static uint16_t cutype;
+LowCore const *lowcore; /* Yes, this *is* a pointer to address 0 */
#define LOADPARM_PROMPT "PROMPT "
#define LOADPARM_EMPTY " "
#define BOOT_MENU_FLAG_MASK (QIPL_FLAG_BM_OPTS_CMD | QIPL_FLAG_BM_OPTS_ZIPL)
/*
- * Priniciples of Operations (SA22-7832-09) chapter 17 requires that
+ * Principles of Operations (SA22-7832-09) chapter 17 requires that
* a subsystem-identification is at 184-187 and bytes 188-191 are zero
* after list-directed-IPL and ccw-IPL.
*/
@@ -48,29 +54,64 @@ unsigned int get_loadparm_index(void)
return atoui(loadparm_str);
}
-static bool find_dev(Schib *schib, int dev_no)
+/*
+ * Find the subchannel connected to the given device (dev_no) and fill in the
+ * subchannel information block (schib) with the connected subchannel's info.
+ * NOTE: The global variable blk_schid is updated to contain the subchannel
+ * information.
+ *
+ * If the caller gives dev_no=-1 then the user did not specify a boot device.
+ * In this case we'll just use the first potentially bootable device we find.
+ */
+static bool find_subch(int dev_no)
{
+ Schib schib;
int i, r;
+ bool is_virtio;
for (i = 0; i < 0x10000; i++) {
blk_schid.sch_no = i;
- r = stsch_err(blk_schid, schib);
+ r = stsch_err(blk_schid, &schib);
if ((r == 3) || (r == -EIO)) {
break;
}
- if (!schib->pmcw.dnv) {
- continue;
- }
- if (!virtio_is_supported(blk_schid)) {
+ if (!schib.pmcw.dnv) {
continue;
}
- /* Skip net devices since no IPLB is created and therefore no
- * no network bootloader has been loaded
+
+ enable_subchannel(blk_schid);
+ cutype = cu_type(blk_schid);
+
+ /*
+ * Note: we always have to run virtio_is_supported() here to make
+ * sure that the vdev.senseid data gets pre-initialized correctly
*/
- if (virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) {
- continue;
+ is_virtio = virtio_is_supported(blk_schid);
+
+ /* No specific devno given, just return 1st possibly bootable device */
+ if (dev_no < 0) {
+ switch (cutype) {
+ case CU_TYPE_VIRTIO:
+ if (is_virtio) {
+ /*
+ * Skip net devices since no IPLB is created and therefore
+ * no network bootloader has been loaded
+ */
+ if (virtio_get_device_type() != VIRTIO_ID_NET) {
+ return true;
+ }
+ }
+ continue;
+ case CU_TYPE_DASD_3990:
+ case CU_TYPE_DASD_2107:
+ return true;
+ default:
+ continue;
+ }
}
- if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) {
+
+ /* Caller asked for a specific devno */
+ if (schib.pmcw.dev == dev_no) {
return true;
}
}
@@ -99,68 +140,88 @@ static void menu_setup(void)
}
}
-static void virtio_setup(void)
+/*
+ * Initialize the channel I/O subsystem so we can talk to our ipl/boot device.
+ */
+static void css_setup(void)
{
- Schib schib;
- int ssid;
- bool found = false;
- uint16_t dev_no;
- char ldp[] = "LOADPARM=[________]\n";
- VDev *vdev = virtio_get_device();
- QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
-
/*
- * We unconditionally enable mss support. In every sane configuration,
- * this will succeed; and even if it doesn't, stsch_err() can deal
- * with the consequences.
+ * Unconditionally enable mss support. In every sane configuration this
+ * will succeed; and even if it doesn't, stsch_err() can handle it.
*/
enable_mss_facility();
+}
+
+/*
+ * Collect various pieces of information from the hypervisor/hardware that
+ * we'll use to determine exactly how we'll boot.
+ */
+static void boot_setup(void)
+{
+ char lpmsg[] = "LOADPARM=[________]\n";
sclp_get_loadparm_ascii(loadparm_str);
- memcpy(ldp + 10, loadparm_str, LOADPARM_LEN);
- sclp_print(ldp);
+ memcpy(lpmsg + 10, loadparm_str, 8);
+ sclp_print(lpmsg);
- memcpy(&qipl, early_qipl, sizeof(QemuIplParameters));
+ have_iplb = store_iplb(&iplb);
+}
- if (store_iplb(&iplb)) {
- switch (iplb.pbt) {
- case S390_IPL_TYPE_CCW:
- dev_no = iplb.ccw.devno;
- debug_print_int("device no. ", dev_no);
- blk_schid.ssid = iplb.ccw.ssid & 0x3;
- debug_print_int("ssid ", blk_schid.ssid);
- found = find_dev(&schib, dev_no);
- break;
- case S390_IPL_TYPE_QEMU_SCSI:
- vdev->scsi_device_selected = true;
- vdev->selected_scsi_device.channel = iplb.scsi.channel;
- vdev->selected_scsi_device.target = iplb.scsi.target;
- vdev->selected_scsi_device.lun = iplb.scsi.lun;
- blk_schid.ssid = iplb.scsi.ssid & 0x3;
- found = find_dev(&schib, iplb.scsi.devno);
- break;
- default:
- panic("List-directed IPL not supported yet!\n");
- }
- menu_setup();
- } else {
+static void find_boot_device(void)
+{
+ VDev *vdev = virtio_get_device();
+ int ssid;
+ bool found;
+
+ if (!have_iplb) {
for (ssid = 0; ssid < 0x3; ssid++) {
blk_schid.ssid = ssid;
- found = find_dev(&schib, -1);
+ found = find_subch(-1);
if (found) {
- break;
+ return;
}
}
+ panic("Could not find a suitable boot device (none specified)\n");
+ }
+
+ switch (iplb.pbt) {
+ case S390_IPL_TYPE_CCW:
+ debug_print_int("device no. ", iplb.ccw.devno);
+ blk_schid.ssid = iplb.ccw.ssid & 0x3;
+ debug_print_int("ssid ", blk_schid.ssid);
+ found = find_subch(iplb.ccw.devno);
+ break;
+ case S390_IPL_TYPE_QEMU_SCSI:
+ vdev->scsi_device_selected = true;
+ vdev->selected_scsi_device.channel = iplb.scsi.channel;
+ vdev->selected_scsi_device.target = iplb.scsi.target;
+ vdev->selected_scsi_device.lun = iplb.scsi.lun;
+ blk_schid.ssid = iplb.scsi.ssid & 0x3;
+ found = find_subch(iplb.scsi.devno);
+ break;
+ default:
+ panic("List-directed IPL not supported yet!\n");
}
- IPL_assert(found, "No virtio device found");
+ IPL_assert(found, "Boot device not found\n");
+}
+
+static void virtio_setup(void)
+{
+ VDev *vdev = virtio_get_device();
+ QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS;
+
+ memcpy(&qipl, early_qipl, sizeof(QemuIplParameters));
+
+ if (have_iplb) {
+ menu_setup();
+ }
if (virtio_get_device_type() == VIRTIO_ID_NET) {
sclp_print("Network boot device detected\n");
vdev->netboot_start_addr = qipl.netboot_start_addr;
} else {
virtio_blk_setup_device(blk_schid);
-
IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected");
}
}
@@ -168,9 +229,24 @@ static void virtio_setup(void)
int main(void)
{
sclp_setup();
- virtio_setup();
-
- zipl_load(); /* no return */
+ css_setup();
+ boot_setup();
+ find_boot_device();
+ enable_subchannel(blk_schid);
+
+ switch (cutype) {
+ case CU_TYPE_DASD_3990:
+ case CU_TYPE_DASD_2107:
+ dasd_ipl(blk_schid, cutype); /* no return */
+ break;
+ case CU_TYPE_VIRTIO:
+ virtio_setup();
+ zipl_load(); /* no return */
+ break;
+ default:
+ print_int("Attempting to boot from unexpected device type", cutype);
+ panic("");
+ }
panic("Failed to load OS from hard disk\n");
return 0; /* make compiler happy */
diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak
index 14e96b2aa6..5eefb7c289 100644
--- a/pc-bios/s390-ccw/netboot.mak
+++ b/pc-bios/s390-ccw/netboot.mak
@@ -1,7 +1,7 @@
SLOF_DIR := $(SRC_PATH)/roms/SLOF
-NETOBJS := start.o sclp.o virtio.o virtio-net.o jump2ipl.o netmain.o \
+NETOBJS := start.o sclp.o cio.o virtio.o virtio-net.o jump2ipl.o netmain.o \
libnet.a libc.a
LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include
diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c
index 0392131c27..f3542cb2cf 100644
--- a/pc-bios/s390-ccw/netmain.c
+++ b/pc-bios/s390-ccw/netmain.c
@@ -33,6 +33,7 @@
#include <pxelinux.h>
#include "s390-ccw.h"
+#include "cio.h"
#include "virtio.h"
#define DEFAULT_BOOT_RETRIES 10
@@ -475,6 +476,7 @@ static bool find_net_dev(Schib *schib, int dev_no)
if (!schib->pmcw.dnv) {
continue;
}
+ enable_subchannel(net_schid);
if (!virtio_is_supported(net_schid)) {
continue;
}
diff --git a/pc-bios/s390-ccw/s390-arch.h b/pc-bios/s390-ccw/s390-arch.h
new file mode 100644
index 0000000000..504fc7c2f0
--- /dev/null
+++ b/pc-bios/s390-ccw/s390-arch.h
@@ -0,0 +1,103 @@
+/*
+ * S390 Basic Architecture
+ *
+ * Copyright (c) 2019 Jason J. Herne <jjherne@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#ifndef S390_ARCH_H
+#define S390_ARCH_H
+
+typedef struct PSW {
+ uint64_t mask;
+ uint64_t addr;
+} __attribute__ ((aligned(8))) PSW;
+_Static_assert(sizeof(struct PSW) == 16, "PSW size incorrect");
+
+/* Older PSW format used by LPSW instruction */
+typedef struct PSWLegacy {
+ uint32_t mask;
+ uint32_t addr;
+} __attribute__ ((aligned(8))) PSWLegacy;
+_Static_assert(sizeof(struct PSWLegacy) == 8, "PSWLegacy size incorrect");
+
+/* s390 psw bit masks */
+#define PSW_MASK_IOINT 0x0200000000000000ULL
+#define PSW_MASK_WAIT 0x0002000000000000ULL
+#define PSW_MASK_EAMODE 0x0000000100000000ULL
+#define PSW_MASK_BAMODE 0x0000000080000000ULL
+#define PSW_MASK_ZMODE (PSW_MASK_EAMODE | PSW_MASK_BAMODE)
+
+/* Low core mapping */
+typedef struct LowCore {
+ /* prefix area: defined by architecture */
+ PSWLegacy ipl_psw; /* 0x000 */
+ uint32_t ccw1[2]; /* 0x008 */
+ uint32_t ccw2[2]; /* 0x010 */
+ uint8_t pad1[0x80 - 0x18]; /* 0x018 */
+ uint32_t ext_params; /* 0x080 */
+ uint16_t cpu_addr; /* 0x084 */
+ uint16_t ext_int_code; /* 0x086 */
+ uint16_t svc_ilen; /* 0x088 */
+ uint16_t svc_code; /* 0x08a */
+ uint16_t pgm_ilen; /* 0x08c */
+ uint16_t pgm_code; /* 0x08e */
+ uint32_t data_exc_code; /* 0x090 */
+ uint16_t mon_class_num; /* 0x094 */
+ uint16_t per_perc_atmid; /* 0x096 */
+ uint64_t per_address; /* 0x098 */
+ uint8_t exc_access_id; /* 0x0a0 */
+ uint8_t per_access_id; /* 0x0a1 */
+ uint8_t op_access_id; /* 0x0a2 */
+ uint8_t ar_access_id; /* 0x0a3 */
+ uint8_t pad2[0xA8 - 0xA4]; /* 0x0a4 */
+ uint64_t trans_exc_code; /* 0x0a8 */
+ uint64_t monitor_code; /* 0x0b0 */
+ uint16_t subchannel_id; /* 0x0b8 */
+ uint16_t subchannel_nr; /* 0x0ba */
+ uint32_t io_int_parm; /* 0x0bc */
+ uint32_t io_int_word; /* 0x0c0 */
+ uint8_t pad3[0xc8 - 0xc4]; /* 0x0c4 */
+ uint32_t stfl_fac_list; /* 0x0c8 */
+ uint8_t pad4[0xe8 - 0xcc]; /* 0x0cc */
+ uint64_t mcic; /* 0x0e8 */
+ uint8_t pad5[0xf4 - 0xf0]; /* 0x0f0 */
+ uint32_t external_damage_code; /* 0x0f4 */
+ uint64_t failing_storage_address; /* 0x0f8 */
+ uint8_t pad6[0x110 - 0x100]; /* 0x100 */
+ uint64_t per_breaking_event_addr; /* 0x110 */
+ uint8_t pad7[0x120 - 0x118]; /* 0x118 */
+ PSW restart_old_psw; /* 0x120 */
+ PSW external_old_psw; /* 0x130 */
+ PSW svc_old_psw; /* 0x140 */
+ PSW program_old_psw; /* 0x150 */
+ PSW mcck_old_psw; /* 0x160 */
+ PSW io_old_psw; /* 0x170 */
+ uint8_t pad8[0x1a0 - 0x180]; /* 0x180 */
+ PSW restart_new_psw; /* 0x1a0 */
+ PSW external_new_psw; /* 0x1b0 */
+ PSW svc_new_psw; /* 0x1c0 */
+ PSW program_new_psw; /* 0x1d0 */
+ PSW mcck_new_psw; /* 0x1e0 */
+ PSW io_new_psw; /* 0x1f0 */
+} __attribute__((packed, aligned(8192))) LowCore;
+
+extern LowCore const *lowcore;
+
+static inline void set_prefix(uint32_t address)
+{
+ asm volatile("spx %0" : : "m" (address) : "memory");
+}
+
+static inline uint32_t store_prefix(void)
+{
+ uint32_t address;
+
+ asm volatile("stpx %0" : "=m" (address));
+ return address;
+}
+
+#endif
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index 9828aa233d..11bce7d73c 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -49,17 +49,10 @@ typedef unsigned long long __u64;
#include "cio.h"
#include "iplb.h"
-typedef struct irb Irb;
-typedef struct ccw1 Ccw1;
-typedef struct cmd_orb CmdOrb;
-typedef struct schib Schib;
-typedef struct chsc_area_sda ChscAreaSda;
-typedef struct senseid SenseId;
-typedef struct subchannel_id SubChannelId;
-
/* start.s */
void disabled_wait(void);
void consume_sclp_int(void);
+void consume_io_int(void);
/* main.c */
void panic(const char *string);
@@ -80,7 +73,6 @@ unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
bool virtio_is_supported(SubChannelId schid);
void virtio_blk_setup_device(SubChannelId schid);
int virtio_read(ulong sector, void *load_addr);
-int enable_mss_facility(void);
u64 get_clock(void);
ulong get_second(void);
diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S
index 5c22cb0849..aa8fceb19d 100644
--- a/pc-bios/s390-ccw/start.S
+++ b/pc-bios/s390-ccw/start.S
@@ -71,6 +71,26 @@ consume_sclp_int:
larl %r1, enabled_wait_psw
lpswe 0(%r1)
+/*
+ * void consume_io_int(void)
+ *
+ * eats one I/O interrupt
+ */
+ .globl consume_io_int
+consume_io_int:
+ /* enable I/O interrupts in cr6 */
+ stctg %c6,%c6,0(%r15)
+ oi 4(%r15), 0xff
+ lctlg %c6,%c6,0(%r15)
+ /* prepare i/o call handler */
+ larl %r1, io_new_code
+ stg %r1, 0x1f8
+ larl %r1, io_new_mask
+ mvc 0x1f0(8),0(%r1)
+ /* load enabled wait PSW */
+ larl %r1, enabled_wait_psw
+ lpswe 0(%r1)
+
external_new_code:
/* disable service interrupts in cr0 */
stctg %c0,%c0,0(%r15)
@@ -78,6 +98,13 @@ external_new_code:
lctlg %c0,%c0,0(%r15)
br %r14
+io_new_code:
+ /* disable I/O interrupts in cr6 */
+ stctg %c6,%c6,0(%r15)
+ ni 4(%r15), 0x00
+ lctlg %c6,%c6,0(%r15)
+ br %r14
+
.align 8
disabled_wait_psw:
.quad 0x0002000180000000,0x0000000000000000
@@ -85,3 +112,5 @@ enabled_wait_psw:
.quad 0x0302000180000000,0x0000000000000000
external_new_mask:
.quad 0x0000000180000000
+io_new_mask:
+ .quad 0x0000000180000000
diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index cdb66f459e..fb40ca9828 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -10,9 +10,11 @@
#include "libc.h"
#include "s390-ccw.h"
+#include "cio.h"
#include "virtio.h"
#include "virtio-scsi.h"
#include "bswap.h"
+#include "helper.h"
#define VRING_WAIT_REPLY_TIMEOUT 30
@@ -20,8 +22,6 @@ static VRing block[VIRTIO_MAX_VQS];
static char ring_area[VIRTIO_RING_SIZE * VIRTIO_MAX_VQS]
__attribute__((__aligned__(PAGE_SIZE)));
-static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
-
static VDev vdev = {
.nr_vqs = 1,
.vrings = block,
@@ -90,38 +90,19 @@ int drain_irqs(SubChannelId schid)
}
}
-static int run_ccw(VDev *vdev, int cmd, void *ptr, int len)
+static int run_ccw(VDev *vdev, int cmd, void *ptr, int len, bool sli)
{
Ccw1 ccw = {};
- CmdOrb orb = {};
- Schib schib;
- int r;
-
- /* start command processing */
- stsch_err(vdev->schid, &schib);
- /* enable the subchannel for IPL device */
- schib.pmcw.ena = 1;
- msch(vdev->schid, &schib);
-
- /* start subchannel command */
- orb.fmt = 1;
- orb.cpa = (u32)(long)&ccw;
- orb.lpm = 0x80;
ccw.cmd_code = cmd;
ccw.cda = (long)ptr;
ccw.count = len;
- r = ssch(vdev->schid, &orb);
- /*
- * XXX Wait until device is done processing the CCW. For now we can
- * assume that a simple tsch will have finished the CCW processing,
- * but the architecture allows for asynchronous operation
- */
- if (!r) {
- r = drain_irqs(vdev->schid);
+ if (sli) {
+ ccw.flags |= CCW_FLAG_SLI;
}
- return r;
+
+ return do_cio(vdev->schid, vdev->senseid.cu_type, ptr2u32(&ccw), CCW_FMT1);
}
static void vring_init(VRing *vr, VqInfo *info)
@@ -263,7 +244,7 @@ void virtio_setup_ccw(VDev *vdev)
vdev->config.blk.blk_size = 0; /* mark "illegal" - setup started... */
vdev->guessed_disk_nature = VIRTIO_GDN_NONE;
- run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0);
+ run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0, false);
switch (vdev->senseid.cu_model) {
case VIRTIO_ID_NET:
@@ -284,18 +265,19 @@ void virtio_setup_ccw(VDev *vdev)
default:
panic("Unsupported virtio device\n");
}
- IPL_assert(run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size) == 0,
- "Could not get block device configuration");
+ IPL_assert(
+ run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size, false) == 0,
+ "Could not get block device configuration");
/* Feature negotiation */
for (i = 0; i < ARRAY_SIZE(vdev->guest_features); i++) {
feats.features = 0;
feats.index = i;
- rc = run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats));
+ rc = run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats), false);
IPL_assert(rc == 0, "Could not get features bits");
vdev->guest_features[i] &= bswap32(feats.features);
feats.features = bswap32(vdev->guest_features[i]);
- rc = run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats));
+ rc = run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats), false);
IPL_assert(rc == 0, "Could not set features bits");
}
@@ -312,16 +294,17 @@ void virtio_setup_ccw(VDev *vdev)
};
IPL_assert(
- run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config)) == 0,
+ run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config), false) == 0,
"Could not get block device VQ configuration");
info.num = config.num;
vring_init(&vdev->vrings[i], &info);
vdev->vrings[i].schid = vdev->schid;
- IPL_assert(run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info)) == 0,
- "Cannot set VQ info");
+ IPL_assert(
+ run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info), false) == 0,
+ "Cannot set VQ info");
}
IPL_assert(
- run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status)) == 0,
+ run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false) == 0,
"Could not write status to host");
}
@@ -329,8 +312,15 @@ bool virtio_is_supported(SubChannelId schid)
{
vdev.schid = schid;
memset(&vdev.senseid, 0, sizeof(vdev.senseid));
- /* run sense id command */
- if (run_ccw(&vdev, CCW_CMD_SENSE_ID, &vdev.senseid, sizeof(vdev.senseid))) {
+
+ /*
+ * Run sense id command.
+ * The size of the senseid data differs between devices (notably,
+ * between virtio devices and dasds), so specify the largest possible
+ * size and suppress the incorrect length indication for smaller sizes.
+ */
+ if (run_ccw(&vdev, CCW_CMD_SENSE_ID, &vdev.senseid, sizeof(vdev.senseid),
+ true)) {
return false;
}
if (vdev.senseid.cu_type == 0x3832) {
@@ -343,20 +333,3 @@ bool virtio_is_supported(SubChannelId schid)
}
return false;
}
-
-int enable_mss_facility(void)
-{
- int ret;
- ChscAreaSda *sda_area = (ChscAreaSda *) chsc_page;
-
- memset(sda_area, 0, PAGE_SIZE);
- sda_area->request.length = 0x0400;
- sda_area->request.code = 0x0031;
- sda_area->operation_code = 0x2;
-
- ret = chsc(sda_area);
- if ((ret == 0) && (sda_area->response.code == 0x0001)) {
- return 0;
- }
- return -EIO;
-}
diff --git a/pc-bios/s390-netboot.img b/pc-bios/s390-netboot.img
index 2c6886efb8..aa90fbccb1 100644
--- a/pc-bios/s390-netboot.img
+++ b/pc-bios/s390-netboot.img
Binary files differ
diff --git a/qemu-options.hx b/qemu-options.hx
index 08749a3391..bdc74c0620 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4233,6 +4233,11 @@ using the SNIA NVM programming model (e.g. Intel NVDIMM).
If @option{pmem} is set to 'on', QEMU will take necessary operations to
guarantee the persistence of its own writes to @option{mem-path}
(e.g. in vNVDIMM label emulation and live migration).
+Also, we will map the backend-file with MAP_SYNC flag, which ensures the
+file metadata is in sync for @option{mem-path} in case of host crash
+or a power failure. MAP_SYNC requires support from both the host kernel
+(since Linux kernel 4.15) and the filesystem of @option{mem-path} mounted
+with DAX option.
@item -object memory-backend-ram,id=@var{id},merge=@var{on|off},dump=@var{on|off},share=@var{on|off},prealloc=@var{on|off},size=@var{size},host-nodes=@var{host-nodes},policy=@var{default|preferred|bind|interleave}
diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
index a310a9072b..c3819d2b98 100755
--- a/scripts/update-linux-headers.sh
+++ b/scripts/update-linux-headers.sh
@@ -95,7 +95,7 @@ for arch in $ARCHLIST; do
rm -rf "$output/linux-headers/asm-$arch"
mkdir -p "$output/linux-headers/asm-$arch"
- for header in kvm.h unistd.h bitsperlong.h; do
+ for header in kvm.h unistd.h bitsperlong.h mman.h; do
cp "$tmpdir/include/asm/$header" "$output/linux-headers/asm-$arch"
done
@@ -139,13 +139,13 @@ done
rm -rf "$output/linux-headers/linux"
mkdir -p "$output/linux-headers/linux"
for header in kvm.h vfio.h vfio_ccw.h vhost.h \
- psci.h psp-sev.h userfaultfd.h; do
+ psci.h psp-sev.h userfaultfd.h mman.h; do
cp "$tmpdir/include/linux/$header" "$output/linux-headers/linux"
done
rm -rf "$output/linux-headers/asm-generic"
mkdir -p "$output/linux-headers/asm-generic"
-for header in unistd.h bitsperlong.h; do
+for header in unistd.h bitsperlong.h mman-common.h mman.h hugetlb_encode.h; do
cp "$tmpdir/include/asm-generic/$header" "$output/linux-headers/asm-generic"
done
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index e1687f7547..722c5514d4 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -2935,6 +2935,56 @@ static X86CPUDefinition builtin_x86_defs[] = {
.model_id = "AMD EPYC Processor (with IBPB)",
.cache_info = &epyc_cache_info,
},
+ {
+ .name = "Dhyana",
+ .level = 0xd,
+ .vendor = CPUID_VENDOR_HYGON,
+ .family = 24,
+ .model = 0,
+ .stepping = 1,
+ .features[FEAT_1_EDX] =
+ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | CPUID_CLFLUSH |
+ CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | CPUID_PGE |
+ CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | CPUID_MCE |
+ CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | CPUID_DE |
+ CPUID_VME | CPUID_FP87,
+ .features[FEAT_1_ECX] =
+ CPUID_EXT_RDRAND | CPUID_EXT_F16C | CPUID_EXT_AVX |
+ CPUID_EXT_XSAVE | CPUID_EXT_POPCNT |
+ CPUID_EXT_MOVBE | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
+ CPUID_EXT_CX16 | CPUID_EXT_FMA | CPUID_EXT_SSSE3 |
+ CPUID_EXT_MONITOR | CPUID_EXT_SSE3,
+ .features[FEAT_8000_0001_EDX] =
+ CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_PDPE1GB |
+ CPUID_EXT2_FFXSR | CPUID_EXT2_MMXEXT | CPUID_EXT2_NX |
+ CPUID_EXT2_SYSCALL,
+ .features[FEAT_8000_0001_ECX] =
+ CPUID_EXT3_OSVW | CPUID_EXT3_3DNOWPREFETCH |
+ CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | CPUID_EXT3_ABM |
+ CPUID_EXT3_CR8LEG | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM |
+ CPUID_EXT3_TOPOEXT,
+ .features[FEAT_8000_0008_EBX] =
+ CPUID_8000_0008_EBX_IBPB,
+ .features[FEAT_7_0_EBX] =
+ CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_AVX2 |
+ CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_RDSEED |
+ CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLFLUSHOPT,
+ /*
+ * Missing: XSAVES (not supported by some Linux versions,
+ * including v4.1 to v4.12).
+ * KVM doesn't yet expose any XSAVES state save component.
+ */
+ .features[FEAT_XSAVE] =
+ CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC |
+ CPUID_XSAVE_XGETBV1,
+ .features[FEAT_6_EAX] =
+ CPUID_6_EAX_ARAT,
+ .features[FEAT_SVM] =
+ CPUID_SVM_NPT | CPUID_SVM_NRIPSAVE,
+ .xlevel = 0x8000001E,
+ .model_id = "Hygon Dhyana Processor",
+ .cache_info = &epyc_cache_info,
+ },
};
typedef struct PropValue {
@@ -4541,6 +4591,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
break;
case 0x8000001D:
*eax = 0;
+ if (cpu->cache_info_passthrough) {
+ host_cpuid(index, count, eax, ebx, ecx, edx);
+ break;
+ }
switch (count) {
case 0: /* L1 dcache info */
encode_cache_cpuid8000001d(env->cache_info_amd.l1d_cache, cs,
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 828067bd1c..0128910661 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -726,6 +726,8 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
#define CPUID_VENDOR_VIA "CentaurHauls"
+#define CPUID_VENDOR_HYGON "HygonGenuine"
+
#define CPUID_MWAIT_IBE (1U << 1) /* Interrupts can exit capability */
#define CPUID_MWAIT_EMX (1U << 0) /* enumeration supported */
diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
index 7c75963e3c..9d7050b5fa 100644
--- a/target/ppc/cpu-models.c
+++ b/target/ppc/cpu-models.c
@@ -740,7 +740,7 @@
POWERPC_DEF("7457a_v1.2", CPU_POWERPC_74x7A_v12, 7455,
"PowerPC 7457A v1.2 (G4)")
/* 64 bits PowerPC */
-#if defined (TARGET_PPC64)
+#if defined(TARGET_PPC64)
POWERPC_DEF("970_v2.2", CPU_POWERPC_970_v22, 970,
"PowerPC 970 v2.2")
POWERPC_DEF("970fx_v1.0", CPU_POWERPC_970FX_v10, 970,
diff --git a/target/ppc/cpu-models.h b/target/ppc/cpu-models.h
index efdb2fa53c..4fdb73034d 100644
--- a/target/ppc/cpu-models.h
+++ b/target/ppc/cpu-models.h
@@ -393,7 +393,8 @@ enum {
CPU_POWERPC_RS64IV = 0x00370000,
#endif /* defined(TARGET_PPC64) */
/* Original POWER */
- /* XXX: should be POWER (RIOS), RSC3308, RSC4608,
+ /*
+ * XXX: should be POWER (RIOS), RSC3308, RSC4608,
* POWER2 (RIOS2) & RSC2 (P2SC) here
*/
/* PA Semi core */
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index d5259f7dd3..5e7cf54b2f 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -23,23 +23,28 @@
#include "qemu-common.h"
#include "qemu/int128.h"
-//#define PPC_EMULATE_32BITS_HYPV
+/* #define PPC_EMULATE_32BITS_HYPV */
-#if defined (TARGET_PPC64)
+#if defined(TARGET_PPC64)
/* PowerPC 64 definitions */
#define TARGET_LONG_BITS 64
#define TARGET_PAGE_BITS 12
#define TCG_GUEST_DEFAULT_MO 0
-/* Note that the official physical address space bits is 62-M where M
- is implementation dependent. I've not looked up M for the set of
- cpus we emulate at the system level. */
+/*
+ * Note that the official physical address space bits is 62-M where M
+ * is implementation dependent. I've not looked up M for the set of
+ * cpus we emulate at the system level.
+ */
#define TARGET_PHYS_ADDR_SPACE_BITS 62
-/* Note that the PPC environment architecture talks about 80 bit virtual
- addresses, with segmentation. Obviously that's not all visible to a
- single process, which is all we're concerned with here. */
+/*
+ * Note that the PPC environment architecture talks about 80 bit
+ * virtual addresses, with segmentation. Obviously that's not all
+ * visible to a single process, which is all we're concerned with
+ * here.
+ */
#ifdef TARGET_ABI32
# define TARGET_VIRT_ADDR_SPACE_BITS 32
#else
@@ -49,7 +54,7 @@
#define TARGET_PAGE_BITS_64K 16
#define TARGET_PAGE_BITS_16M 24
-#else /* defined (TARGET_PPC64) */
+#else /* defined(TARGET_PPC64) */
/* PowerPC 32 definitions */
#define TARGET_LONG_BITS 32
#define TARGET_PAGE_BITS 12
@@ -57,14 +62,14 @@
#define TARGET_PHYS_ADDR_SPACE_BITS 36
#define TARGET_VIRT_ADDR_SPACE_BITS 32
-#endif /* defined (TARGET_PPC64) */
+#endif /* defined(TARGET_PPC64) */
#define CPUArchState struct CPUPPCState
#include "exec/cpu-defs.h"
#include "cpu-qom.h"
-#if defined (TARGET_PPC64)
+#if defined(TARGET_PPC64)
#define PPC_ELF_MACHINE EM_PPC64
#else
#define PPC_ELF_MACHINE EM_PPC
@@ -237,9 +242,11 @@ struct ppc_spr_t {
const char *name;
target_ulong default_value;
#ifdef CONFIG_KVM
- /* We (ab)use the fact that all the SPRs will have ids for the
+ /*
+ * We (ab)use the fact that all the SPRs will have ids for the
* ONE_REG interface will have KVM_REG_PPC to use 0 as meaning,
- * don't sync this */
+ * don't sync this
+ */
uint64_t one_reg_id;
#endif
};
@@ -656,39 +663,39 @@ enum {
#define fpscr_eex (((env->fpscr) >> FPSCR_XX) & ((env->fpscr) >> FPSCR_XE) & \
0x1F)
-#define FP_FX (1ull << FPSCR_FX)
-#define FP_FEX (1ull << FPSCR_FEX)
-#define FP_VX (1ull << FPSCR_VX)
-#define FP_OX (1ull << FPSCR_OX)
-#define FP_UX (1ull << FPSCR_UX)
-#define FP_ZX (1ull << FPSCR_ZX)
-#define FP_XX (1ull << FPSCR_XX)
-#define FP_VXSNAN (1ull << FPSCR_VXSNAN)
-#define FP_VXISI (1ull << FPSCR_VXISI)
-#define FP_VXIDI (1ull << FPSCR_VXIDI)
-#define FP_VXZDZ (1ull << FPSCR_VXZDZ)
-#define FP_VXIMZ (1ull << FPSCR_VXIMZ)
-#define FP_VXVC (1ull << FPSCR_VXVC)
-#define FP_FR (1ull << FSPCR_FR)
-#define FP_FI (1ull << FPSCR_FI)
-#define FP_C (1ull << FPSCR_C)
-#define FP_FL (1ull << FPSCR_FL)
-#define FP_FG (1ull << FPSCR_FG)
-#define FP_FE (1ull << FPSCR_FE)
-#define FP_FU (1ull << FPSCR_FU)
-#define FP_FPCC (FP_FL | FP_FG | FP_FE | FP_FU)
-#define FP_FPRF (FP_C | FP_FL | FP_FG | FP_FE | FP_FU)
-#define FP_VXSOFT (1ull << FPSCR_VXSOFT)
-#define FP_VXSQRT (1ull << FPSCR_VXSQRT)
-#define FP_VXCVI (1ull << FPSCR_VXCVI)
-#define FP_VE (1ull << FPSCR_VE)
-#define FP_OE (1ull << FPSCR_OE)
-#define FP_UE (1ull << FPSCR_UE)
-#define FP_ZE (1ull << FPSCR_ZE)
-#define FP_XE (1ull << FPSCR_XE)
-#define FP_NI (1ull << FPSCR_NI)
-#define FP_RN1 (1ull << FPSCR_RN1)
-#define FP_RN (1ull << FPSCR_RN)
+#define FP_FX (1ull << FPSCR_FX)
+#define FP_FEX (1ull << FPSCR_FEX)
+#define FP_VX (1ull << FPSCR_VX)
+#define FP_OX (1ull << FPSCR_OX)
+#define FP_UX (1ull << FPSCR_UX)
+#define FP_ZX (1ull << FPSCR_ZX)
+#define FP_XX (1ull << FPSCR_XX)
+#define FP_VXSNAN (1ull << FPSCR_VXSNAN)
+#define FP_VXISI (1ull << FPSCR_VXISI)
+#define FP_VXIDI (1ull << FPSCR_VXIDI)
+#define FP_VXZDZ (1ull << FPSCR_VXZDZ)
+#define FP_VXIMZ (1ull << FPSCR_VXIMZ)
+#define FP_VXVC (1ull << FPSCR_VXVC)
+#define FP_FR (1ull << FSPCR_FR)
+#define FP_FI (1ull << FPSCR_FI)
+#define FP_C (1ull << FPSCR_C)
+#define FP_FL (1ull << FPSCR_FL)
+#define FP_FG (1ull << FPSCR_FG)
+#define FP_FE (1ull << FPSCR_FE)
+#define FP_FU (1ull << FPSCR_FU)
+#define FP_FPCC (FP_FL | FP_FG | FP_FE | FP_FU)
+#define FP_FPRF (FP_C | FP_FL | FP_FG | FP_FE | FP_FU)
+#define FP_VXSOFT (1ull << FPSCR_VXSOFT)
+#define FP_VXSQRT (1ull << FPSCR_VXSQRT)
+#define FP_VXCVI (1ull << FPSCR_VXCVI)
+#define FP_VE (1ull << FPSCR_VE)
+#define FP_OE (1ull << FPSCR_OE)
+#define FP_UE (1ull << FPSCR_UE)
+#define FP_ZE (1ull << FPSCR_ZE)
+#define FP_XE (1ull << FPSCR_XE)
+#define FP_NI (1ull << FPSCR_NI)
+#define FP_RN1 (1ull << FPSCR_RN1)
+#define FP_RN (1ull << FPSCR_RN)
/* the exception bits which can be cleared by mcrfs - includes FX */
#define FP_EX_CLEAR_BITS (FP_FX | FP_OX | FP_UX | FP_ZX | \
@@ -698,8 +705,8 @@ enum {
/*****************************************************************************/
/* Vector status and control register */
-#define VSCR_NJ 16 /* Vector non-java */
-#define VSCR_SAT 0 /* Vector saturation */
+#define VSCR_NJ 16 /* Vector non-java */
+#define VSCR_SAT 0 /* Vector saturation */
/*****************************************************************************/
/* BookE e500 MMU registers */
@@ -962,9 +969,10 @@ struct ppc_radix_page_info {
/*****************************************************************************/
/* The whole PowerPC CPU context */
-/* PowerPC needs eight modes for different hypervisor/supervisor/guest +
- * real/paged mode combinations. The other two modes are for external PID
- * load/store.
+/*
+ * PowerPC needs eight modes for different hypervisor/supervisor/guest
+ * + real/paged mode combinations. The other two modes are for
+ * external PID load/store.
*/
#define NB_MMU_MODES 10
#define MMU_MODE8_SUFFIX _epl
@@ -976,8 +984,9 @@ struct ppc_radix_page_info {
#define PPC_CPU_INDIRECT_OPCODES_LEN 0x20
struct CPUPPCState {
- /* First are the most commonly used resources
- * during translated code execution
+ /*
+ * First are the most commonly used resources during translated
+ * code execution
*/
/* general purpose registers */
target_ulong gpr[32];
@@ -1023,8 +1032,8 @@ struct CPUPPCState {
/* High part of 128-bit helper return. */
uint64_t retxh;
- int access_type; /* when a memory exception occurs, the access
- type is stored here */
+ /* when a memory exception occurs, the access type is stored here */
+ int access_type;
CPU_COMMON
@@ -1072,8 +1081,10 @@ struct CPUPPCState {
/* SPE registers */
uint64_t spe_acc;
uint32_t spe_fscr;
- /* SPE and Altivec can share a status since they will never be used
- * simultaneously */
+ /*
+ * SPE and Altivec can share a status since they will never be
+ * used simultaneously
+ */
float_status vec_status;
/* Internal devices resources */
@@ -1103,7 +1114,8 @@ struct CPUPPCState {
int error_code;
uint32_t pending_interrupts;
#if !defined(CONFIG_USER_ONLY)
- /* This is the IRQ controller, which is implementation dependent
+ /*
+ * This is the IRQ controller, which is implementation dependent
* and only relevant when emulating a complete machine.
*/
uint32_t irq_input_state;
@@ -1117,7 +1129,8 @@ struct CPUPPCState {
hwaddr mpic_iack;
/* true when the external proxy facility mode is enabled */
bool mpic_proxy;
- /* set when the processor has an HV mode, thus HV priv
+ /*
+ * set when the processor has an HV mode, thus HV priv
* instructions and SPRs are diallowed if MSR:HV is 0
*/
bool has_hv_mode;
@@ -1149,8 +1162,10 @@ struct CPUPPCState {
/* booke timers */
- /* Specifies bit locations of the Time Base used to signal a fixed timer
- * exception on a transition from 0 to 1. (watchdog or fixed-interval timer)
+ /*
+ * Specifies bit locations of the Time Base used to signal a fixed
+ * timer exception on a transition from 0 to 1. (watchdog or
+ * fixed-interval timer)
*
* 0 selects the least significant bit.
* 63 selects the most significant bit.
@@ -1250,8 +1265,8 @@ struct PPCVirtualHypervisorClass {
void (*unmap_hptes)(PPCVirtualHypervisor *vhyp,
const ppc_hash_pte64_t *hptes,
hwaddr ptex, int n);
- void (*store_hpte)(PPCVirtualHypervisor *vhyp, hwaddr ptex,
- uint64_t pte0, uint64_t pte1);
+ void (*hpte_set_c)(PPCVirtualHypervisor *vhyp, hwaddr ptex, uint64_t pte1);
+ void (*hpte_set_r)(PPCVirtualHypervisor *vhyp, hwaddr ptex, uint64_t pte1);
void (*get_pate)(PPCVirtualHypervisor *vhyp, ppc_v3_pate_t *entry);
target_ulong (*encode_hpt_for_kvm_pr)(PPCVirtualHypervisor *vhyp);
};
@@ -1290,53 +1305,54 @@ extern const struct VMStateDescription vmstate_ppc_cpu;
/*****************************************************************************/
void ppc_translate_init(void);
-/* you can call this signal handler from your SIGBUS and SIGSEGV
- signal handlers to inform the virtual CPU of exceptions. non zero
- is returned if the signal was handled by the virtual CPU. */
-int cpu_ppc_signal_handler (int host_signum, void *pinfo,
- void *puc);
+/*
+ * you can call this signal handler from your SIGBUS and SIGSEGV
+ * signal handlers to inform the virtual CPU of exceptions. non zero
+ * is returned if the signal was handled by the virtual CPU.
+ */
+int cpu_ppc_signal_handler(int host_signum, void *pinfo, void *puc);
#if defined(CONFIG_USER_ONLY)
int ppc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
int mmu_idx);
#endif
#if !defined(CONFIG_USER_ONLY)
-void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
+void ppc_store_sdr1(CPUPPCState *env, target_ulong value);
void ppc_store_ptcr(CPUPPCState *env, target_ulong value);
#endif /* !defined(CONFIG_USER_ONLY) */
-void ppc_store_msr (CPUPPCState *env, target_ulong value);
+void ppc_store_msr(CPUPPCState *env, target_ulong value);
void ppc_cpu_list(void);
/* Time-base and decrementer management */
#ifndef NO_CPU_IO_DEFS
-uint64_t cpu_ppc_load_tbl (CPUPPCState *env);
-uint32_t cpu_ppc_load_tbu (CPUPPCState *env);
-void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value);
-void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value);
-uint64_t cpu_ppc_load_atbl (CPUPPCState *env);
-uint32_t cpu_ppc_load_atbu (CPUPPCState *env);
-void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value);
-void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value);
+uint64_t cpu_ppc_load_tbl(CPUPPCState *env);
+uint32_t cpu_ppc_load_tbu(CPUPPCState *env);
+void cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value);
+void cpu_ppc_store_tbl(CPUPPCState *env, uint32_t value);
+uint64_t cpu_ppc_load_atbl(CPUPPCState *env);
+uint32_t cpu_ppc_load_atbu(CPUPPCState *env);
+void cpu_ppc_store_atbl(CPUPPCState *env, uint32_t value);
+void cpu_ppc_store_atbu(CPUPPCState *env, uint32_t value);
bool ppc_decr_clear_on_delivery(CPUPPCState *env);
target_ulong cpu_ppc_load_decr(CPUPPCState *env);
void cpu_ppc_store_decr(CPUPPCState *env, target_ulong value);
target_ulong cpu_ppc_load_hdecr(CPUPPCState *env);
void cpu_ppc_store_hdecr(CPUPPCState *env, target_ulong value);
-uint64_t cpu_ppc_load_purr (CPUPPCState *env);
-uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env);
-uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env);
+uint64_t cpu_ppc_load_purr(CPUPPCState *env);
+uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env);
+uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env);
#if !defined(CONFIG_USER_ONLY)
-void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value);
-void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value);
-target_ulong load_40x_pit (CPUPPCState *env);
-void store_40x_pit (CPUPPCState *env, target_ulong val);
-void store_40x_dbcr0 (CPUPPCState *env, uint32_t val);
-void store_40x_sler (CPUPPCState *env, uint32_t val);
-void store_booke_tcr (CPUPPCState *env, target_ulong val);
-void store_booke_tsr (CPUPPCState *env, target_ulong val);
-void ppc_tlb_invalidate_all (CPUPPCState *env);
-void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr);
+void cpu_ppc601_store_rtcl(CPUPPCState *env, uint32_t value);
+void cpu_ppc601_store_rtcu(CPUPPCState *env, uint32_t value);
+target_ulong load_40x_pit(CPUPPCState *env);
+void store_40x_pit(CPUPPCState *env, target_ulong val);
+void store_40x_dbcr0(CPUPPCState *env, uint32_t val);
+void store_40x_sler(CPUPPCState *env, uint32_t val);
+void store_booke_tcr(CPUPPCState *env, target_ulong val);
+void store_booke_tsr(CPUPPCState *env, target_ulong val);
+void ppc_tlb_invalidate_all(CPUPPCState *env);
+void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr);
void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp);
#endif
#endif
@@ -1349,7 +1365,8 @@ static inline uint64_t ppc_dump_gpr(CPUPPCState *env, int gprn)
gprv = env->gpr[gprn];
if (env->flags & POWERPC_FLAG_SPE) {
- /* If the CPU implements the SPE extension, we have to get the
+ /*
+ * If the CPU implements the SPE extension, we have to get the
* high bits of the GPR from the gprh storage area
*/
gprv &= 0xFFFFFFFFULL;
@@ -1360,8 +1377,8 @@ static inline uint64_t ppc_dump_gpr(CPUPPCState *env, int gprn)
}
/* Device control registers */
-int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp);
-int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val);
+int ppc_dcr_read(ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp);
+int ppc_dcr_write(ppc_dcr_t *dcr_env, int dcrn, uint32_t val);
#define POWERPC_CPU_TYPE_SUFFIX "-" TYPE_POWERPC_CPU
#define POWERPC_CPU_TYPE_NAME(model) model POWERPC_CPU_TYPE_SUFFIX
@@ -1372,7 +1389,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val);
/* MMU modes definitions */
#define MMU_USER_IDX 0
-static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
+static inline int cpu_mmu_index(CPUPPCState *env, bool ifetch)
{
return ifetch ? env->immu_idx : env->dmmu_idx;
}
@@ -1990,17 +2007,17 @@ void ppc_compat_add_property(Object *obj, const char *name,
/* External Input Interrupt Directed to Guest State */
#define EPCR_EXTGS (1 << 31)
-#define L1CSR0_CPE 0x00010000 /* Data Cache Parity Enable */
-#define L1CSR0_CUL 0x00000400 /* (D-)Cache Unable to Lock */
-#define L1CSR0_DCLFR 0x00000100 /* D-Cache Lock Flash Reset */
-#define L1CSR0_DCFI 0x00000002 /* Data Cache Flash Invalidate */
-#define L1CSR0_DCE 0x00000001 /* Data Cache Enable */
+#define L1CSR0_CPE 0x00010000 /* Data Cache Parity Enable */
+#define L1CSR0_CUL 0x00000400 /* (D-)Cache Unable to Lock */
+#define L1CSR0_DCLFR 0x00000100 /* D-Cache Lock Flash Reset */
+#define L1CSR0_DCFI 0x00000002 /* Data Cache Flash Invalidate */
+#define L1CSR0_DCE 0x00000001 /* Data Cache Enable */
-#define L1CSR1_CPE 0x00010000 /* Instruction Cache Parity Enable */
-#define L1CSR1_ICUL 0x00000400 /* I-Cache Unable to Lock */
-#define L1CSR1_ICLFR 0x00000100 /* I-Cache Lock Flash Reset */
-#define L1CSR1_ICFI 0x00000002 /* Instruction Cache Flash Invalidate */
-#define L1CSR1_ICE 0x00000001 /* Instruction Cache Enable */
+#define L1CSR1_CPE 0x00010000 /* Instruction Cache Parity Enable */
+#define L1CSR1_ICUL 0x00000400 /* I-Cache Unable to Lock */
+#define L1CSR1_ICLFR 0x00000100 /* I-Cache Lock Flash Reset */
+#define L1CSR1_ICFI 0x00000002 /* Instruction Cache Flash Invalidate */
+#define L1CSR1_ICE 0x00000001 /* Instruction Cache Enable */
/* HID0 bits */
#define HID0_DEEPNAP (1 << 24) /* pre-2.06 */
@@ -2226,7 +2243,8 @@ enum {
};
/*****************************************************************************/
-/* Memory access type :
+/*
+ * Memory access type :
* may be needed for precise access rights control and precise exceptions.
*/
enum {
@@ -2242,8 +2260,9 @@ enum {
ACCESS_CACHE = 0x60, /* Cache manipulation */
};
-/* Hardware interruption sources:
- * all those exception can be raised simulteaneously
+/*
+ * Hardware interrupt sources:
+ * all those exception can be raised simulteaneously
*/
/* Input pins definitions */
enum {
@@ -2325,9 +2344,11 @@ enum {
enum {
/* POWER7 input pins */
POWER7_INPUT_INT = 0,
- /* POWER7 probably has other inputs, but we don't care about them
+ /*
+ * POWER7 probably has other inputs, but we don't care about them
* for any existing machine. We can wire these up when we need
- * them */
+ * them
+ */
POWER7_INPUT_NB,
};
diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c
index 9164fe701b..f102177572 100644
--- a/target/ppc/dfp_helper.c
+++ b/target/ppc/dfp_helper.c
@@ -1104,19 +1104,19 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t s) \
} \
} \
\
- while (offset < (size)/4) { \
+ while (offset < (size) / 4) { \
n++; \
- digits[(size)/4-n] = dfp_get_bcd_digit_##size(dfp.b64, offset++); \
- if (digits[(size)/4-n] > 10) { \
+ digits[(size) / 4 - n] = dfp_get_bcd_digit_##size(dfp.b64, offset++); \
+ if (digits[(size) / 4 - n] > 10) { \
dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE); \
return; \
} else { \
- nonzero |= (digits[(size)/4-n] > 0); \
+ nonzero |= (digits[(size) / 4 - n] > 0); \
} \
} \
\
if (nonzero) { \
- decNumberSetBCD(&dfp.t, digits+((size)/4)-n, n); \
+ decNumberSetBCD(&dfp.t, digits + ((size) / 4) - n, n); \
} \
\
if (s && sgn) { \
@@ -1170,13 +1170,13 @@ DFP_HELPER_XEX(dxexq, 128)
static void dfp_set_raw_exp_64(uint64_t *t, uint64_t raw)
{
*t &= 0x8003ffffffffffffULL;
- *t |= (raw << (63-13));
+ *t |= (raw << (63 - 13));
}
static void dfp_set_raw_exp_128(uint64_t *t, uint64_t raw)
{
t[HI_IDX] &= 0x80003fffffffffffULL;
- t[HI_IDX] |= (raw << (63-17));
+ t[HI_IDX] |= (raw << (63 - 17));
}
#define DFP_HELPER_IEX(op, size) \
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index beafcf1ebd..ec2c177091 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -25,9 +25,9 @@
#include "internal.h"
#include "helper_regs.h"
-//#define DEBUG_OP
-//#define DEBUG_SOFTWARE_TLB
-//#define DEBUG_EXCEPTIONS
+/* #define DEBUG_OP */
+/* #define DEBUG_SOFTWARE_TLB */
+/* #define DEBUG_EXCEPTIONS */
#ifdef DEBUG_EXCEPTIONS
# define LOG_EXCP(...) qemu_log(__VA_ARGS__)
@@ -126,8 +126,9 @@ static uint64_t ppc_excp_vector_offset(CPUState *cs, int ail)
return offset;
}
-/* Note that this function should be greatly optimized
- * when called with a constant excp, from ppc_hw_interrupt
+/*
+ * Note that this function should be greatly optimized when called
+ * with a constant excp, from ppc_hw_interrupt
*/
static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
{
@@ -147,7 +148,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
msr = env->msr & ~0x783f0000ULL;
}
- /* new interrupt handler msr preserves existing HV and ME unless
+ /*
+ * new interrupt handler msr preserves existing HV and ME unless
* explicitly overriden
*/
new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
@@ -166,7 +168,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
excp = powerpc_reset_wakeup(cs, env, excp, &msr);
}
- /* Exception targetting modifiers
+ /*
+ * Exception targetting modifiers
*
* LPES0 is supported on POWER7/8/9
* LPES1 is not supported (old iSeries mode)
@@ -194,7 +197,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
ail = 0;
}
- /* Hypervisor emulation assistance interrupt only exists on server
+ /*
+ * Hypervisor emulation assistance interrupt only exists on server
* arch 2.05 server or later. We also don't want to generate it if
* we don't have HVB in msr_mask (PAPR mode).
*/
@@ -229,8 +233,9 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
break;
case POWERPC_EXCP_MCHECK: /* Machine check exception */
if (msr_me == 0) {
- /* Machine check exception is not enabled.
- * Enter checkstop state.
+ /*
+ * Machine check exception is not enabled. Enter
+ * checkstop state.
*/
fprintf(stderr, "Machine check while not allowed. "
"Entering checkstop state\n");
@@ -242,8 +247,9 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
cpu_interrupt_exittb(cs);
}
if (env->msr_mask & MSR_HVB) {
- /* ISA specifies HV, but can be delivered to guest with HV clear
- * (e.g., see FWNMI in PAPR).
+ /*
+ * ISA specifies HV, but can be delivered to guest with HV
+ * clear (e.g., see FWNMI in PAPR).
*/
new_msr |= (target_ulong)MSR_HVB;
}
@@ -294,9 +300,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
break;
case POWERPC_EXCP_ALIGN: /* Alignment exception */
/* Get rS/rD and rA from faulting opcode */
- /* Note: the opcode fields will not be set properly for a direct
- * store load/store, but nobody cares as nobody actually uses
- * direct store segments.
+ /*
+ * Note: the opcode fields will not be set properly for a
+ * direct store load/store, but nobody cares as nobody
+ * actually uses direct store segments.
*/
env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
break;
@@ -310,7 +317,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
return;
}
- /* FP exceptions always have NIP pointing to the faulting
+ /*
+ * FP exceptions always have NIP pointing to the faulting
* instruction, so always use store_next and claim we are
* precise in the MSR.
*/
@@ -341,7 +349,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
dump_syscall(env);
lev = env->error_code;
- /* We need to correct the NIP which in this case is supposed
+ /*
+ * We need to correct the NIP which in this case is supposed
* to point to the next instruction
*/
env->nip += 4;
@@ -425,8 +434,9 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
new_msr |= ((target_ulong)1 << MSR_ME);
}
if (env->msr_mask & MSR_HVB) {
- /* ISA specifies HV, but can be delivered to guest with HV clear
- * (e.g., see FWNMI in PAPR, NMI injection in QEMU).
+ /*
+ * ISA specifies HV, but can be delivered to guest with HV
+ * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU).
*/
new_msr |= (target_ulong)MSR_HVB;
} else {
@@ -675,7 +685,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
env->spr[asrr1] = env->spr[srr1];
}
- /* Sort out endianness of interrupt, this differs depending on the
+ /*
+ * Sort out endianness of interrupt, this differs depending on the
* CPU, the HV mode, etc...
*/
#ifdef TARGET_PPC64
@@ -716,8 +727,9 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
}
vector |= env->excp_prefix;
- /* AIL only works if there is no HV transition and we are running with
- * translations enabled
+ /*
+ * AIL only works if there is no HV transition and we are running
+ * with translations enabled
*/
if (!((msr >> MSR_IR) & 1) || !((msr >> MSR_DR) & 1) ||
((new_msr & MSR_HVB) && !(msr & MSR_HVB))) {
@@ -745,8 +757,9 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
}
}
#endif
- /* We don't use hreg_store_msr here as already have treated
- * any special case that could occur. Just store MSR and update hflags
+ /*
+ * We don't use hreg_store_msr here as already have treated any
+ * special case that could occur. Just store MSR and update hflags
*
* Note: We *MUST* not use hreg_store_msr() as-is anyway because it
* will prevent setting of the HV bit which some exceptions might need
@@ -762,8 +775,9 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
/* Reset the reservation */
env->reserve_addr = -1;
- /* Any interrupt is context synchronizing, check if TCG TLB
- * needs a delayed flush on ppc64
+ /*
+ * Any interrupt is context synchronizing, check if TCG TLB needs
+ * a delayed flush on ppc64
*/
check_tlb_flush(env, false);
}
@@ -1015,8 +1029,9 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
cs = CPU(ppc_env_get_cpu(env));
cs->halted = 1;
- /* The architecture specifies that HDEC interrupts are
- * discarded in PM states
+ /*
+ * The architecture specifies that HDEC interrupts are discarded
+ * in PM states
*/
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
@@ -1047,8 +1062,9 @@ static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
#if defined(DEBUG_OP)
cpu_dump_rfi(env->nip, env->msr);
#endif
- /* No need to raise an exception here,
- * as rfi is always the last insn of a TB
+ /*
+ * No need to raise an exception here, as rfi is always the last
+ * insn of a TB
*/
cpu_interrupt_exittb(cs);
/* Reset the reservation */
@@ -1067,8 +1083,9 @@ void helper_rfi(CPUPPCState *env)
#if defined(TARGET_PPC64)
void helper_rfid(CPUPPCState *env)
{
- /* The architeture defines a number of rules for which bits
- * can change but in practice, we handle this in hreg_store_msr()
+ /*
+ * The architeture defines a number of rules for which bits can
+ * change but in practice, we handle this in hreg_store_msr()
* which will be called by do_rfi(), so there is no need to filter
* here
*/
@@ -1206,9 +1223,11 @@ static int book3s_dbell2irq(target_ulong rb)
{
int msg = rb & DBELL_TYPE_MASK;
- /* A Directed Hypervisor Doorbell message is sent only if the
+ /*
+ * A Directed Hypervisor Doorbell message is sent only if the
* message type is 5. All other types are reserved and the
- * instruction is a no-op */
+ * instruction is a no-op
+ */
return msg == DBELL_TYPE_DBELL_SERVER ? PPC_INTERRUPT_HDOORBELL : -1;
}
diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c
index 2ed4f42275..0b7308f539 100644
--- a/target/ppc/fpu_helper.c
+++ b/target/ppc/fpu_helper.c
@@ -90,10 +90,12 @@ uint32_t helper_tosingle(uint64_t arg)
ret = extract64(arg, 62, 2) << 30;
ret |= extract64(arg, 29, 30);
} else {
- /* Zero or Denormal result. If the exponent is in bounds for
- * a single-precision denormal result, extract the proper bits.
- * If the input is not zero, and the exponent is out of bounds,
- * then the result is undefined; this underflows to zero.
+ /*
+ * Zero or Denormal result. If the exponent is in bounds for
+ * a single-precision denormal result, extract the proper
+ * bits. If the input is not zero, and the exponent is out of
+ * bounds, then the result is undefined; this underflows to
+ * zero.
*/
ret = extract64(arg, 63, 1) << 31;
if (unlikely(exp >= 874)) {
@@ -1090,7 +1092,7 @@ uint32_t helper_ftsqrt(uint64_t frb)
fe_flag = 1;
} else if (unlikely(float64_is_neg(frb))) {
fe_flag = 1;
- } else if (!float64_is_zero(frb) && (e_b <= (-1022+52))) {
+ } else if (!float64_is_zero(frb) && (e_b <= (-1022 + 52))) {
fe_flag = 1;
}
@@ -1789,7 +1791,8 @@ uint32_t helper_efdcmpeq(CPUPPCState *env, uint64_t op1, uint64_t op2)
#define float64_to_float64(x, env) x
-/* VSX_ADD_SUB - VSX floating point add/subract
+/*
+ * VSX_ADD_SUB - VSX floating point add/subract
* name - instruction mnemonic
* op - operation (add or sub)
* nels - number of elements (1, 2 or 4)
@@ -1872,7 +1875,8 @@ void helper_xsaddqp(CPUPPCState *env, uint32_t opcode)
do_float_check_status(env, GETPC());
}
-/* VSX_MUL - VSX floating point multiply
+/*
+ * VSX_MUL - VSX floating point multiply
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
@@ -1950,7 +1954,8 @@ void helper_xsmulqp(CPUPPCState *env, uint32_t opcode)
do_float_check_status(env, GETPC());
}
-/* VSX_DIV - VSX floating point divide
+/*
+ * VSX_DIV - VSX floating point divide
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
@@ -2034,7 +2039,8 @@ void helper_xsdivqp(CPUPPCState *env, uint32_t opcode)
do_float_check_status(env, GETPC());
}
-/* VSX_RE - VSX floating point reciprocal estimate
+/*
+ * VSX_RE - VSX floating point reciprocal estimate
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
@@ -2075,7 +2081,8 @@ VSX_RE(xsresp, 1, float64, VsrD(0), 1, 1)
VSX_RE(xvredp, 2, float64, VsrD(i), 0, 0)
VSX_RE(xvresp, 4, float32, VsrW(i), 0, 0)
-/* VSX_SQRT - VSX floating point square root
+/*
+ * VSX_SQRT - VSX floating point square root
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
@@ -2124,7 +2131,8 @@ VSX_SQRT(xssqrtsp, 1, float64, VsrD(0), 1, 1)
VSX_SQRT(xvsqrtdp, 2, float64, VsrD(i), 0, 0)
VSX_SQRT(xvsqrtsp, 4, float32, VsrW(i), 0, 0)
-/* VSX_RSQRTE - VSX floating point reciprocal square root estimate
+/*
+ *VSX_RSQRTE - VSX floating point reciprocal square root estimate
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
@@ -2174,7 +2182,8 @@ VSX_RSQRTE(xsrsqrtesp, 1, float64, VsrD(0), 1, 1)
VSX_RSQRTE(xvrsqrtedp, 2, float64, VsrD(i), 0, 0)
VSX_RSQRTE(xvrsqrtesp, 4, float32, VsrW(i), 0, 0)
-/* VSX_TDIV - VSX floating point test for divide
+/*
+ * VSX_TDIV - VSX floating point test for divide
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
@@ -2207,18 +2216,20 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
if (unlikely(tp##_is_any_nan(xa.fld) || \
tp##_is_any_nan(xb.fld))) { \
fe_flag = 1; \
- } else if ((e_b <= emin) || (e_b >= (emax-2))) { \
+ } else if ((e_b <= emin) || (e_b >= (emax - 2))) { \
fe_flag = 1; \
} else if (!tp##_is_zero(xa.fld) && \
(((e_a - e_b) >= emax) || \
- ((e_a - e_b) <= (emin+1)) || \
- (e_a <= (emin+nbits)))) { \
+ ((e_a - e_b) <= (emin + 1)) || \
+ (e_a <= (emin + nbits)))) { \
fe_flag = 1; \
} \
\
if (unlikely(tp##_is_zero_or_denormal(xb.fld))) { \
- /* XB is not zero because of the above check and */ \
- /* so must be denormalized. */ \
+ /* \
+ * XB is not zero because of the above check and so \
+ * must be denormalized. \
+ */ \
fg_flag = 1; \
} \
} \
@@ -2231,7 +2242,8 @@ VSX_TDIV(xstdivdp, 1, float64, VsrD(0), -1022, 1023, 52)
VSX_TDIV(xvtdivdp, 2, float64, VsrD(i), -1022, 1023, 52)
VSX_TDIV(xvtdivsp, 4, float32, VsrW(i), -126, 127, 23)
-/* VSX_TSQRT - VSX floating point test for square root
+/*
+ * VSX_TSQRT - VSX floating point test for square root
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
@@ -2266,13 +2278,15 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
} else if (unlikely(tp##_is_neg(xb.fld))) { \
fe_flag = 1; \
} else if (!tp##_is_zero(xb.fld) && \
- (e_b <= (emin+nbits))) { \
+ (e_b <= (emin + nbits))) { \
fe_flag = 1; \
} \
\
if (unlikely(tp##_is_zero_or_denormal(xb.fld))) { \
- /* XB is not zero because of the above check and */ \
- /* therefore must be denormalized. */ \
+ /* \
+ * XB is not zero because of the above check and \
+ * therefore must be denormalized. \
+ */ \
fg_flag = 1; \
} \
} \
@@ -2285,7 +2299,8 @@ VSX_TSQRT(xstsqrtdp, 1, float64, VsrD(0), -1022, 52)
VSX_TSQRT(xvtsqrtdp, 2, float64, VsrD(i), -1022, 52)
VSX_TSQRT(xvtsqrtsp, 4, float32, VsrW(i), -126, 23)
-/* VSX_MADD - VSX floating point muliply/add variations
+/*
+ * VSX_MADD - VSX floating point muliply/add variations
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
@@ -2322,8 +2337,10 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
float_status tstat = env->fp_status; \
set_float_exception_flags(0, &tstat); \
if (r2sp && (tstat.float_rounding_mode == float_round_nearest_even)) {\
- /* Avoid double rounding errors by rounding the intermediate */ \
- /* result to odd. */ \
+ /* \
+ * Avoid double rounding errors by rounding the intermediate \
+ * result to odd. \
+ */ \
set_float_rounding_mode(float_round_to_zero, &tstat); \
xt_out.fld = tp##_muladd(xa.fld, b->fld, c->fld, \
maddflgs, &tstat); \
@@ -2388,7 +2405,8 @@ VSX_MADD(xvnmaddmsp, 4, float32, VsrW(i), NMADD_FLGS, 0, 0, 0)
VSX_MADD(xvnmsubasp, 4, float32, VsrW(i), NMSUB_FLGS, 1, 0, 0)
VSX_MADD(xvnmsubmsp, 4, float32, VsrW(i), NMSUB_FLGS, 0, 0, 0)
-/* VSX_SCALAR_CMP_DP - VSX scalar floating point compare double precision
+/*
+ * VSX_SCALAR_CMP_DP - VSX scalar floating point compare double precision
* op - instruction mnemonic
* cmp - comparison operation
* exp - expected result of comparison
@@ -2604,7 +2622,8 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
VSX_SCALAR_CMPQ(xscmpoqp, 1)
VSX_SCALAR_CMPQ(xscmpuqp, 0)
-/* VSX_MAX_MIN - VSX floating point maximum/minimum
+/*
+ * VSX_MAX_MIN - VSX floating point maximum/minimum
* name - instruction mnemonic
* op - operation (max or min)
* nels - number of elements (1, 2 or 4)
@@ -2733,7 +2752,8 @@ void helper_##name(CPUPPCState *env, uint32_t opcode) \
VSX_MAX_MINJ(xsmaxjdp, 1);
VSX_MAX_MINJ(xsminjdp, 0);
-/* VSX_CMP - VSX floating point compare
+/*
+ * VSX_CMP - VSX floating point compare
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
@@ -2778,7 +2798,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
} \
\
putVSR(xT(opcode), &xt, env); \
- if ((opcode >> (31-21)) & 1) { \
+ if ((opcode >> (31 - 21)) & 1) { \
env->crf[6] = (all_true ? 0x8 : 0) | (all_false ? 0x2 : 0); \
} \
do_float_check_status(env, GETPC()); \
@@ -2793,7 +2813,8 @@ VSX_CMP(xvcmpgesp, 4, float32, VsrW(i), le, 1, 1)
VSX_CMP(xvcmpgtsp, 4, float32, VsrW(i), lt, 1, 1)
VSX_CMP(xvcmpnesp, 4, float32, VsrW(i), eq, 0, 0)
-/* VSX_CVT_FP_TO_FP - VSX floating point/floating point conversion
+/*
+ * VSX_CVT_FP_TO_FP - VSX floating point/floating point conversion
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* stp - source type (float32 or float64)
@@ -2829,10 +2850,11 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
VSX_CVT_FP_TO_FP(xscvdpsp, 1, float64, float32, VsrD(0), VsrW(0), 1)
VSX_CVT_FP_TO_FP(xscvspdp, 1, float32, float64, VsrW(0), VsrD(0), 1)
-VSX_CVT_FP_TO_FP(xvcvdpsp, 2, float64, float32, VsrD(i), VsrW(2*i), 0)
-VSX_CVT_FP_TO_FP(xvcvspdp, 2, float32, float64, VsrW(2*i), VsrD(i), 0)
+VSX_CVT_FP_TO_FP(xvcvdpsp, 2, float64, float32, VsrD(i), VsrW(2 * i), 0)
+VSX_CVT_FP_TO_FP(xvcvspdp, 2, float32, float64, VsrW(2 * i), VsrD(i), 0)
-/* VSX_CVT_FP_TO_FP_VECTOR - VSX floating point/floating point conversion
+/*
+ * VSX_CVT_FP_TO_FP_VECTOR - VSX floating point/floating point conversion
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* stp - source type (float32 or float64)
@@ -2868,7 +2890,8 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
VSX_CVT_FP_TO_FP_VECTOR(xscvdpqp, 1, float64, float128, VsrD(0), f128, 1)
-/* VSX_CVT_FP_TO_FP_HP - VSX floating point/floating point conversion
+/*
+ * VSX_CVT_FP_TO_FP_HP - VSX floating point/floating point conversion
* involving one half precision value
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
@@ -2953,7 +2976,8 @@ uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb)
return float32_to_float64(xb >> 32, &tstat);
}
-/* VSX_CVT_FP_TO_INT - VSX floating point to integer conversion
+/*
+ * VSX_CVT_FP_TO_INT - VSX floating point to integer conversion
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* stp - source type (float32 or float64)
@@ -2996,17 +3020,18 @@ VSX_CVT_FP_TO_INT(xscvdpuxds, 1, float64, uint64, VsrD(0), VsrD(0), 0ULL)
VSX_CVT_FP_TO_INT(xscvdpuxws, 1, float64, uint32, VsrD(0), VsrW(1), 0U)
VSX_CVT_FP_TO_INT(xvcvdpsxds, 2, float64, int64, VsrD(i), VsrD(i), \
0x8000000000000000ULL)
-VSX_CVT_FP_TO_INT(xvcvdpsxws, 2, float64, int32, VsrD(i), VsrW(2*i), \
+VSX_CVT_FP_TO_INT(xvcvdpsxws, 2, float64, int32, VsrD(i), VsrW(2 * i), \
0x80000000U)
VSX_CVT_FP_TO_INT(xvcvdpuxds, 2, float64, uint64, VsrD(i), VsrD(i), 0ULL)
-VSX_CVT_FP_TO_INT(xvcvdpuxws, 2, float64, uint32, VsrD(i), VsrW(2*i), 0U)
-VSX_CVT_FP_TO_INT(xvcvspsxds, 2, float32, int64, VsrW(2*i), VsrD(i), \
+VSX_CVT_FP_TO_INT(xvcvdpuxws, 2, float64, uint32, VsrD(i), VsrW(2 * i), 0U)
+VSX_CVT_FP_TO_INT(xvcvspsxds, 2, float32, int64, VsrW(2 * i), VsrD(i), \
0x8000000000000000ULL)
VSX_CVT_FP_TO_INT(xvcvspsxws, 4, float32, int32, VsrW(i), VsrW(i), 0x80000000U)
-VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, VsrW(2*i), VsrD(i), 0ULL)
+VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, VsrW(2 * i), VsrD(i), 0ULL)
VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, VsrW(i), VsrW(i), 0U)
-/* VSX_CVT_FP_TO_INT_VECTOR - VSX floating point to integer conversion
+/*
+ * VSX_CVT_FP_TO_INT_VECTOR - VSX floating point to integer conversion
* op - instruction mnemonic
* stp - source type (float32 or float64)
* ttp - target type (int32, uint32, int64 or uint64)
@@ -3040,7 +3065,8 @@ VSX_CVT_FP_TO_INT_VECTOR(xscvqpswz, float128, int32, f128, VsrD(0), \
VSX_CVT_FP_TO_INT_VECTOR(xscvqpudz, float128, uint64, f128, VsrD(0), 0x0ULL)
VSX_CVT_FP_TO_INT_VECTOR(xscvqpuwz, float128, uint32, f128, VsrD(0), 0x0ULL)
-/* VSX_CVT_INT_TO_FP - VSX integer to floating point conversion
+/*
+ * VSX_CVT_INT_TO_FP - VSX integer to floating point conversion
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* stp - source type (int32, uint32, int64 or uint64)
@@ -3079,14 +3105,15 @@ VSX_CVT_INT_TO_FP(xscvsxdsp, 1, int64, float64, VsrD(0), VsrD(0), 1, 1)
VSX_CVT_INT_TO_FP(xscvuxdsp, 1, uint64, float64, VsrD(0), VsrD(0), 1, 1)
VSX_CVT_INT_TO_FP(xvcvsxddp, 2, int64, float64, VsrD(i), VsrD(i), 0, 0)
VSX_CVT_INT_TO_FP(xvcvuxddp, 2, uint64, float64, VsrD(i), VsrD(i), 0, 0)
-VSX_CVT_INT_TO_FP(xvcvsxwdp, 2, int32, float64, VsrW(2*i), VsrD(i), 0, 0)
-VSX_CVT_INT_TO_FP(xvcvuxwdp, 2, uint64, float64, VsrW(2*i), VsrD(i), 0, 0)
-VSX_CVT_INT_TO_FP(xvcvsxdsp, 2, int64, float32, VsrD(i), VsrW(2*i), 0, 0)
-VSX_CVT_INT_TO_FP(xvcvuxdsp, 2, uint64, float32, VsrD(i), VsrW(2*i), 0, 0)
+VSX_CVT_INT_TO_FP(xvcvsxwdp, 2, int32, float64, VsrW(2 * i), VsrD(i), 0, 0)
+VSX_CVT_INT_TO_FP(xvcvuxwdp, 2, uint64, float64, VsrW(2 * i), VsrD(i), 0, 0)
+VSX_CVT_INT_TO_FP(xvcvsxdsp, 2, int64, float32, VsrD(i), VsrW(2 * i), 0, 0)
+VSX_CVT_INT_TO_FP(xvcvuxdsp, 2, uint64, float32, VsrD(i), VsrW(2 * i), 0, 0)
VSX_CVT_INT_TO_FP(xvcvsxwsp, 4, int32, float32, VsrW(i), VsrW(i), 0, 0)
VSX_CVT_INT_TO_FP(xvcvuxwsp, 4, uint32, float32, VsrW(i), VsrW(i), 0, 0)
-/* VSX_CVT_INT_TO_FP_VECTOR - VSX integer to floating point conversion
+/*
+ * VSX_CVT_INT_TO_FP_VECTOR - VSX integer to floating point conversion
* op - instruction mnemonic
* stp - source type (int32, uint32, int64 or uint64)
* ttp - target type (float32 or float64)
@@ -3111,13 +3138,15 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
VSX_CVT_INT_TO_FP_VECTOR(xscvsdqp, int64, float128, VsrD(0), f128)
VSX_CVT_INT_TO_FP_VECTOR(xscvudqp, uint64, float128, VsrD(0), f128)
-/* For "use current rounding mode", define a value that will not be one of
- * the existing rounding model enums.
+/*
+ * For "use current rounding mode", define a value that will not be
+ * one of the existing rounding model enums.
*/
#define FLOAT_ROUND_CURRENT (float_round_nearest_even + float_round_down + \
float_round_up + float_round_to_zero)
-/* VSX_ROUND - VSX floating point round
+/*
+ * VSX_ROUND - VSX floating point round
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* tp - type (float32 or float64)
@@ -3150,9 +3179,11 @@ void helper_##op(CPUPPCState *env, uint32_t opcode) \
} \
} \
\
- /* If this is not a "use current rounding mode" instruction, \
+ /* \
+ * If this is not a "use current rounding mode" instruction, \
* then inhibit setting of the XX bit and restore rounding \
- * mode from FPSCR */ \
+ * mode from FPSCR \
+ */ \
if (rmode != FLOAT_ROUND_CURRENT) { \
fpscr_set_rounding_mode(env); \
env->fp_status.float_exception_flags &= ~float_flag_inexact; \
@@ -3234,7 +3265,8 @@ void helper_xvxsigsp(CPUPPCState *env, uint32_t opcode)
putVSR(xT(opcode), &xt, env);
}
-/* VSX_TEST_DC - VSX floating point test data class
+/*
+ * VSX_TEST_DC - VSX floating point test data class
* op - instruction mnemonic
* nels - number of elements (1, 2 or 4)
* xbn - VSR register number
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index fbf3821f4b..ce3625f44e 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -33,14 +33,14 @@ static int ppc_gdb_register_len_apple(int n)
return 8;
case 64 ... 95:
return 16;
- case 64+32: /* nip */
- case 65+32: /* msr */
- case 67+32: /* lr */
- case 68+32: /* ctr */
- case 70+32: /* fpscr */
+ case 64 + 32: /* nip */
+ case 65 + 32: /* msr */
+ case 67 + 32: /* lr */
+ case 68 + 32: /* ctr */
+ case 70 + 32: /* fpscr */
return 8;
- case 66+32: /* cr */
- case 69+32: /* xer */
+ case 66 + 32: /* cr */
+ case 69 + 32: /* xer */
return 4;
default:
return 0;
@@ -84,11 +84,14 @@ static int ppc_gdb_register_len(int n)
}
}
-/* We need to present the registers to gdb in the "current" memory ordering.
- For user-only mode we get this for free; TARGET_WORDS_BIGENDIAN is set to
- the proper ordering for the binary, and cannot be changed.
- For system mode, TARGET_WORDS_BIGENDIAN is always set, and we must check
- the current mode of the chip to see if we're running in little-endian. */
+/*
+ * We need to present the registers to gdb in the "current" memory
+ * ordering. For user-only mode we get this for free;
+ * TARGET_WORDS_BIGENDIAN is set to the proper ordering for the
+ * binary, and cannot be changed. For system mode,
+ * TARGET_WORDS_BIGENDIAN is always set, and we must check the current
+ * mode of the chip to see if we're running in little-endian.
+ */
void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len)
{
#ifndef CONFIG_USER_ONLY
@@ -104,11 +107,12 @@ void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len)
#endif
}
-/* Old gdb always expects FP registers. Newer (xml-aware) gdb only
+/*
+ * Old gdb always expects FP registers. Newer (xml-aware) gdb only
* expects whatever the target description contains. Due to a
* historical mishap the FP registers appear in between core integer
- * regs and PC, MSR, CR, and so forth. We hack round this by giving the
- * FP regs zero size when talking to a newer gdb.
+ * regs and PC, MSR, CR, and so forth. We hack round this by giving
+ * the FP regs zero size when talking to a newer gdb.
*/
int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
diff --git a/target/ppc/helper_regs.h b/target/ppc/helper_regs.h
index c863abc0bf..922da76c6c 100644
--- a/target/ppc/helper_regs.h
+++ b/target/ppc/helper_regs.h
@@ -44,10 +44,11 @@ static inline void hreg_swap_gpr_tgpr(CPUPPCState *env)
static inline void hreg_compute_mem_idx(CPUPPCState *env)
{
- /* This is our encoding for server processors. The architecture
+ /*
+ * This is our encoding for server processors. The architecture
* specifies that there is no such thing as userspace with
- * translation off, however it appears that MacOS does it and
- * some 32-bit CPUs support it. Weird...
+ * translation off, however it appears that MacOS does it and some
+ * 32-bit CPUs support it. Weird...
*
* 0 = Guest User space virtual mode
* 1 = Guest Kernel space virtual mode
@@ -143,7 +144,8 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
/* Change the exception prefix on PowerPC 601 */
env->excp_prefix = ((value >> MSR_EP) & 1) * 0xFFF00000;
}
- /* If PR=1 then EE, IR and DR must be 1
+ /*
+ * If PR=1 then EE, IR and DR must be 1
*
* Note: We only enforce this on 64-bit server processors.
* It appears that:
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c
index 162add561e..f6a088ac08 100644
--- a/target/ppc/int_helper.c
+++ b/target/ppc/int_helper.c
@@ -137,7 +137,8 @@ uint64_t helper_divde(CPUPPCState *env, uint64_t rau, uint64_t rbu, uint32_t oe)
/* if x = 0xab, returns 0xababababababababa */
#define pattern(x) (((x) & 0xff) * (~(target_ulong)0 / 0xff))
-/* substract 1 from each byte, and with inverse, check if MSB is set at each
+/*
+ * subtract 1 from each byte, and with inverse, check if MSB is set at each
* byte.
* i.e. ((0x00 - 0x01) & ~(0x00)) & 0x80
* (0xFF & 0xFF) & 0x80 = 0x80 (zero found)
@@ -156,7 +157,8 @@ uint32_t helper_cmpeqb(target_ulong ra, target_ulong rb)
#undef haszero
#undef hasvalue
-/* Return invalid random number.
+/*
+ * Return invalid random number.
*
* FIXME: Add rng backend or other mechanism to get cryptographically suitable
* random number
@@ -181,7 +183,7 @@ uint64_t helper_bpermd(uint64_t rs, uint64_t rb)
uint64_t ra = 0;
for (i = 0; i < 8; i++) {
- int index = (rs >> (i*8)) & 0xFF;
+ int index = (rs >> (i * 8)) & 0xFF;
if (index < 64) {
if (rb & PPC_BIT(index)) {
ra |= 1 << i;
@@ -370,7 +372,8 @@ target_ulong helper_divso(CPUPPCState *env, target_ulong arg1,
/* 602 specific instructions */
/* mfrom is the most crazy instruction ever seen, imho ! */
/* Real implementation uses a ROM table. Do the same */
-/* Extremely decomposed:
+/*
+ * Extremely decomposed:
* -arg / 256
* return 256 * log10(10 + 1.0) + 0.5
*/
@@ -393,7 +396,7 @@ target_ulong helper_602_mfrom(target_ulong arg)
for (index = 0; index < ARRAY_SIZE(r->element); index++)
#else
#define VECTOR_FOR_INORDER_I(index, element) \
- for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
+ for (index = ARRAY_SIZE(r->element) - 1; index >= 0; index--)
#endif
/* Saturating arithmetic helpers. */
@@ -634,7 +637,8 @@ void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
} \
}
-/* VABSDU - Vector absolute difference unsigned
+/*
+ * VABSDU - Vector absolute difference unsigned
* name - instruction mnemonic suffix (b: byte, h: halfword, w: word)
* element - element type to access from vector
*/
@@ -739,7 +743,8 @@ void helper_vcmpne##suffix(CPUPPCState *env, ppc_avr_t *r, \
} \
}
-/* VCMPNEZ - Vector compare not equal to zero
+/*
+ * VCMPNEZ - Vector compare not equal to zero
* suffix - instruction mnemonic suffix (b: byte, h: halfword, w: word)
* element - element type to access from vector
*/
@@ -1138,7 +1143,7 @@ void helper_vpermr(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
#define VBPERMQ_DW(index) (((index) & 0x40) != 0)
#define EXTRACT_BIT(avr, i, index) (extract64((avr)->u64[i], index, 1))
#else
-#define VBPERMQ_INDEX(avr, i) ((avr)->u8[15-(i)])
+#define VBPERMQ_INDEX(avr, i) ((avr)->u8[15 - (i)])
#define VBPERMD_INDEX(i) (1 - i)
#define VBPERMQ_DW(index) (((index) & 0x40) == 0)
#define EXTRACT_BIT(avr, i, index) \
@@ -1169,7 +1174,7 @@ void helper_vbpermq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
int index = VBPERMQ_INDEX(b, i);
if (index < 128) {
- uint64_t mask = (1ull << (63-(index & 0x3F)));
+ uint64_t mask = (1ull << (63 - (index & 0x3F)));
if (a->u64[VBPERMQ_DW(index)] & mask) {
perm |= (0x8000 >> i);
}
@@ -1449,9 +1454,9 @@ void helper_vgbbd(ppc_avr_t *r, ppc_avr_t *b)
VECTOR_FOR_INORDER_I(i, u8) {
#if defined(HOST_WORDS_BIGENDIAN)
- t[i>>3] |= VGBBD_MASKS[b->u8[i]] >> (i & 7);
+ t[i >> 3] |= VGBBD_MASKS[b->u8[i]] >> (i & 7);
#else
- t[i>>3] |= VGBBD_MASKS[b->u8[i]] >> (7-(i & 7));
+ t[i >> 3] |= VGBBD_MASKS[b->u8[i]] >> (7 - (i & 7));
#endif
}
@@ -1463,19 +1468,19 @@ void helper_vgbbd(ppc_avr_t *r, ppc_avr_t *b)
void helper_##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \
int i, j; \
- trgtyp prod[sizeof(ppc_avr_t)/sizeof(a->srcfld[0])]; \
+ trgtyp prod[sizeof(ppc_avr_t) / sizeof(a->srcfld[0])]; \
\
VECTOR_FOR_INORDER_I(i, srcfld) { \
prod[i] = 0; \
for (j = 0; j < sizeof(a->srcfld[0]) * 8; j++) { \
- if (a->srcfld[i] & (1ull<<j)) { \
+ if (a->srcfld[i] & (1ull << j)) { \
prod[i] ^= ((trgtyp)b->srcfld[i] << j); \
} \
} \
} \
\
VECTOR_FOR_INORDER_I(i, trgfld) { \
- r->trgfld[i] = prod[2*i] ^ prod[2*i+1]; \
+ r->trgfld[i] = prod[2 * i] ^ prod[2 * i + 1]; \
} \
}
@@ -1493,7 +1498,7 @@ void helper_vpmsumd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
VECTOR_FOR_INORDER_I(i, u64) {
prod[i] = 0;
for (j = 0; j < 64; j++) {
- if (a->u64[i] & (1ull<<j)) {
+ if (a->u64[i] & (1ull << j)) {
prod[i] ^= (((__uint128_t)b->u64[i]) << j);
}
}
@@ -1508,7 +1513,7 @@ void helper_vpmsumd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
VECTOR_FOR_INORDER_I(i, u64) {
prod[i].VsrD(1) = prod[i].VsrD(0) = 0;
for (j = 0; j < 64; j++) {
- if (a->u64[i] & (1ull<<j)) {
+ if (a->u64[i] & (1ull << j)) {
ppc_avr_t bshift;
if (j == 0) {
bshift.VsrD(0) = 0;
@@ -1548,9 +1553,9 @@ void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
VECTOR_FOR_INORDER_I(j, u32) {
uint32_t e = x[i]->u32[j];
- result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
- ((e >> 6) & 0x3e0) |
- ((e >> 3) & 0x1f));
+ result.u16[4 * i + j] = (((e >> 9) & 0xfc00) |
+ ((e >> 6) & 0x3e0) |
+ ((e >> 3) & 0x1f));
}
}
*r = result;
@@ -1568,7 +1573,7 @@ void helper_vpkpx(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
\
VECTOR_FOR_INORDER_I(i, from) { \
result.to[i] = cvt(a0->from[i], &sat); \
- result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat); \
+ result.to[i + ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat);\
} \
*r = result; \
if (dosat && sat) { \
@@ -1736,9 +1741,11 @@ VEXTU_X_DO(vextuhrx, 16, 0)
VEXTU_X_DO(vextuwrx, 32, 0)
#undef VEXTU_X_DO
-/* The specification says that the results are undefined if all of the
- * shift counts are not identical. We check to make sure that they are
- * to conform to what real hardware appears to do. */
+/*
+ * The specification says that the results are undefined if all of the
+ * shift counts are not identical. We check to make sure that they
+ * are to conform to what real hardware appears to do.
+ */
#define VSHIFT(suffix, leftp) \
void helper_vs##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \
@@ -1805,9 +1812,10 @@ void helper_vsrv(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
int i;
unsigned int shift, bytes;
- /* Use reverse order, as destination and source register can be same. Its
- * being modified in place saving temporary, reverse order will guarantee
- * that computed result is not fed back.
+ /*
+ * Use reverse order, as destination and source register can be
+ * same. Its being modified in place saving temporary, reverse
+ * order will guarantee that computed result is not fed back.
*/
for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) {
shift = b->u8[i] & 0x7; /* extract shift value */
@@ -1840,7 +1848,7 @@ void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
#if defined(HOST_WORDS_BIGENDIAN)
memmove(&r->u8[0], &a->u8[sh], 16 - sh);
- memset(&r->u8[16-sh], 0, sh);
+ memset(&r->u8[16 - sh], 0, sh);
#else
memmove(&r->u8[sh], &a->u8[0], 16 - sh);
memset(&r->u8[0], 0, sh);
@@ -2112,7 +2120,7 @@ void helper_vsum4ubs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
ppc_avr_t result; \
\
for (i = 0; i < ARRAY_SIZE(r->u32); i++) { \
- uint16_t e = b->u16[hi ? i : i+4]; \
+ uint16_t e = b->u16[hi ? i : i + 4]; \
uint8_t a = (e >> 15) ? 0xff : 0; \
uint8_t r = (e >> 10) & 0x1f; \
uint8_t g = (e >> 5) & 0x1f; \
@@ -2463,7 +2471,7 @@ static void bcd_put_digit(ppc_avr_t *bcd, uint8_t digit, int n)
{
if (n & 1) {
bcd->u8[BCD_DIG_BYTE(n)] &= 0x0F;
- bcd->u8[BCD_DIG_BYTE(n)] |= (digit<<4);
+ bcd->u8[BCD_DIG_BYTE(n)] |= (digit << 4);
} else {
bcd->u8[BCD_DIG_BYTE(n)] &= 0xF0;
bcd->u8[BCD_DIG_BYTE(n)] |= digit;
@@ -3220,7 +3228,7 @@ void helper_vshasigmad(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six)
for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
if (st == 0) {
- if ((six & (0x8 >> (2*i))) == 0) {
+ if ((six & (0x8 >> (2 * i))) == 0) {
r->VsrD(i) = ror64(a->VsrD(i), 1) ^
ror64(a->VsrD(i), 8) ^
(a->VsrD(i) >> 7);
@@ -3230,7 +3238,7 @@ void helper_vshasigmad(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six)
(a->VsrD(i) >> 6);
}
} else { /* st == 1 */
- if ((six & (0x8 >> (2*i))) == 0) {
+ if ((six & (0x8 >> (2 * i))) == 0) {
r->VsrD(i) = ror64(a->VsrD(i), 28) ^
ror64(a->VsrD(i), 34) ^
ror64(a->VsrD(i), 39);
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 2427c8ee13..02e22e2017 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -49,24 +49,14 @@
#include "elf.h"
#include "sysemu/kvm_int.h"
-//#define DEBUG_KVM
-
-#ifdef DEBUG_KVM
-#define DPRINTF(fmt, ...) \
- do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) \
- do { } while (0)
-#endif
-
#define PROC_DEVTREE_CPU "/proc/device-tree/cpus/"
const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
KVM_CAP_LAST_INFO
};
-static int cap_interrupt_unset = false;
-static int cap_interrupt_level = false;
+static int cap_interrupt_unset;
+static int cap_interrupt_level;
static int cap_segstate;
static int cap_booke_sregs;
static int cap_ppc_smt;
@@ -96,7 +86,8 @@ static int cap_large_decr;
static uint32_t debug_inst_opcode;
-/* XXX We have a race condition where we actually have a level triggered
+/*
+ * XXX We have a race condition where we actually have a level triggered
* interrupt, but the infrastructure can't expose that yet, so the guest
* takes but ignores it, goes to sleep and never gets notified that there's
* still an interrupt pending.
@@ -114,10 +105,12 @@ static void kvm_kick_cpu(void *opaque)
qemu_cpu_kick(CPU(cpu));
}
-/* Check whether we are running with KVM-PR (instead of KVM-HV). This
+/*
+ * Check whether we are running with KVM-PR (instead of KVM-HV). This
* should only be used for fallback tests - generally we should use
* explicit capabilities for the features we want, rather than
- * assuming what is/isn't available depending on the KVM variant. */
+ * assuming what is/isn't available depending on the KVM variant.
+ */
static bool kvmppc_is_pr(KVMState *ks)
{
/* Assume KVM-PR if the GET_PVINFO capability is available */
@@ -143,8 +136,10 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR);
cap_epr = kvm_check_extension(s, KVM_CAP_PPC_EPR);
cap_ppc_watchdog = kvm_check_extension(s, KVM_CAP_PPC_BOOKE_WATCHDOG);
- /* Note: we don't set cap_papr here, because this capability is
- * only activated after this by kvmppc_set_papr() */
+ /*
+ * Note: we don't set cap_papr here, because this capability is
+ * only activated after this by kvmppc_set_papr()
+ */
cap_htab_fd = kvm_vm_check_extension(s, KVM_CAP_PPC_HTAB_FD);
cap_fixup_hcalls = kvm_check_extension(s, KVM_CAP_PPC_FIXUP_HCALL);
cap_ppc_smt = kvm_vm_check_extension(s, KVM_CAP_PPC_SMT);
@@ -160,7 +155,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
* in KVM at this moment.
*
* TODO: call kvm_vm_check_extension() with the right capability
- * after the kernel starts implementing it.*/
+ * after the kernel starts implementing it.
+ */
cap_ppc_pvr_compat = false;
if (!cap_interrupt_level) {
@@ -186,10 +182,13 @@ static int kvm_arch_sync_sregs(PowerPCCPU *cpu)
int ret;
if (cenv->excp_model == POWERPC_EXCP_BOOKE) {
- /* What we're really trying to say is "if we're on BookE, we use
- the native PVR for now". This is the only sane way to check
- it though, so we potentially confuse users that they can run
- BookE guests on BookS. Let's hope nobody dares enough :) */
+ /*
+ * What we're really trying to say is "if we're on BookE, we
+ * use the native PVR for now". This is the only sane way to
+ * check it though, so we potentially confuse users that they
+ * can run BookE guests on BookS. Let's hope nobody dares
+ * enough :)
+ */
return 0;
} else {
if (!cap_segstate) {
@@ -421,12 +420,14 @@ void kvm_check_mmu(PowerPCCPU *cpu, Error **errp)
}
if (ppc_hash64_has(cpu, PPC_HASH64_CI_LARGEPAGE)) {
- /* Mostly what guest pagesizes we can use are related to the
+ /*
+ * Mostly what guest pagesizes we can use are related to the
* host pages used to map guest RAM, which is handled in the
* platform code. Cache-Inhibited largepages (64k) however are
* used for I/O, so if they're mapped to the host at all it
* will be a normal mapping, not a special hugepage one used
- * for RAM. */
+ * for RAM.
+ */
if (getpagesize() < 0x10000) {
error_setg(errp,
"KVM can't supply 64kiB CI pages, which guest expects");
@@ -440,9 +441,9 @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu)
return POWERPC_CPU(cpu)->vcpu_id;
}
-/* e500 supports 2 h/w breakpoint and 2 watchpoint.
- * book3s supports only 1 watchpoint, so array size
- * of 4 is sufficient for now.
+/*
+ * e500 supports 2 h/w breakpoint and 2 watchpoint. book3s supports
+ * only 1 watchpoint, so array size of 4 is sufficient for now.
*/
#define MAX_HW_BKPTS 4
@@ -497,9 +498,12 @@ int kvm_arch_init_vcpu(CPUState *cs)
break;
case POWERPC_MMU_2_07:
if (!cap_htm && !kvmppc_is_pr(cs->kvm_state)) {
- /* KVM-HV has transactional memory on POWER8 also without the
- * KVM_CAP_PPC_HTM extension, so enable it here instead as
- * long as it's availble to userspace on the host. */
+ /*
+ * KVM-HV has transactional memory on POWER8 also without
+ * the KVM_CAP_PPC_HTM extension, so enable it here
+ * instead as long as it's availble to userspace on the
+ * host.
+ */
if (qemu_getauxval(AT_HWCAP2) & PPC_FEATURE2_HAS_HTM) {
cap_htm = true;
}
@@ -626,7 +630,7 @@ static int kvm_put_fp(CPUState *cs)
reg.addr = (uintptr_t)&fpscr;
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to set FPSCR to KVM: %s\n", strerror(errno));
+ trace_kvm_failed_fpscr_set(strerror(errno));
return ret;
}
@@ -647,8 +651,8 @@ static int kvm_put_fp(CPUState *cs)
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to set %s%d to KVM: %s\n", vsx ? "VSR" : "FPR",
- i, strerror(errno));
+ trace_kvm_failed_fp_set(vsx ? "VSR" : "FPR", i,
+ strerror(errno));
return ret;
}
}
@@ -659,7 +663,7 @@ static int kvm_put_fp(CPUState *cs)
reg.addr = (uintptr_t)&env->vscr;
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to set VSCR to KVM: %s\n", strerror(errno));
+ trace_kvm_failed_vscr_set(strerror(errno));
return ret;
}
@@ -668,7 +672,7 @@ static int kvm_put_fp(CPUState *cs)
reg.addr = (uintptr_t)cpu_avr_ptr(env, i);
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to set VR%d to KVM: %s\n", i, strerror(errno));
+ trace_kvm_failed_vr_set(i, strerror(errno));
return ret;
}
}
@@ -693,7 +697,7 @@ static int kvm_get_fp(CPUState *cs)
reg.addr = (uintptr_t)&fpscr;
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to get FPSCR from KVM: %s\n", strerror(errno));
+ trace_kvm_failed_fpscr_get(strerror(errno));
return ret;
} else {
env->fpscr = fpscr;
@@ -709,8 +713,8 @@ static int kvm_get_fp(CPUState *cs)
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to get %s%d from KVM: %s\n",
- vsx ? "VSR" : "FPR", i, strerror(errno));
+ trace_kvm_failed_fp_get(vsx ? "VSR" : "FPR", i,
+ strerror(errno));
return ret;
} else {
#ifdef HOST_WORDS_BIGENDIAN
@@ -733,7 +737,7 @@ static int kvm_get_fp(CPUState *cs)
reg.addr = (uintptr_t)&env->vscr;
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to get VSCR from KVM: %s\n", strerror(errno));
+ trace_kvm_failed_vscr_get(strerror(errno));
return ret;
}
@@ -742,8 +746,7 @@ static int kvm_get_fp(CPUState *cs)
reg.addr = (uintptr_t)cpu_avr_ptr(env, i);
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to get VR%d from KVM: %s\n",
- i, strerror(errno));
+ trace_kvm_failed_vr_get(i, strerror(errno));
return ret;
}
}
@@ -764,7 +767,7 @@ static int kvm_get_vpa(CPUState *cs)
reg.addr = (uintptr_t)&spapr_cpu->vpa_addr;
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to get VPA address from KVM: %s\n", strerror(errno));
+ trace_kvm_failed_vpa_addr_get(strerror(errno));
return ret;
}
@@ -774,8 +777,7 @@ static int kvm_get_vpa(CPUState *cs)
reg.addr = (uintptr_t)&spapr_cpu->slb_shadow_addr;
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to get SLB shadow state from KVM: %s\n",
- strerror(errno));
+ trace_kvm_failed_slb_get(strerror(errno));
return ret;
}
@@ -785,8 +787,7 @@ static int kvm_get_vpa(CPUState *cs)
reg.addr = (uintptr_t)&spapr_cpu->dtl_addr;
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to get dispatch trace log state from KVM: %s\n",
- strerror(errno));
+ trace_kvm_failed_dtl_get(strerror(errno));
return ret;
}
@@ -800,10 +801,12 @@ static int kvm_put_vpa(CPUState *cs)
struct kvm_one_reg reg;
int ret;
- /* SLB shadow or DTL can't be registered unless a master VPA is
+ /*
+ * SLB shadow or DTL can't be registered unless a master VPA is
* registered. That means when restoring state, if a VPA *is*
* registered, we need to set that up first. If not, we need to
- * deregister the others before deregistering the master VPA */
+ * deregister the others before deregistering the master VPA
+ */
assert(spapr_cpu->vpa_addr
|| !(spapr_cpu->slb_shadow_addr || spapr_cpu->dtl_addr));
@@ -812,7 +815,7 @@ static int kvm_put_vpa(CPUState *cs)
reg.addr = (uintptr_t)&spapr_cpu->vpa_addr;
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to set VPA address to KVM: %s\n", strerror(errno));
+ trace_kvm_failed_vpa_addr_set(strerror(errno));
return ret;
}
}
@@ -823,7 +826,7 @@ static int kvm_put_vpa(CPUState *cs)
reg.addr = (uintptr_t)&spapr_cpu->slb_shadow_addr;
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to set SLB shadow state to KVM: %s\n", strerror(errno));
+ trace_kvm_failed_slb_set(strerror(errno));
return ret;
}
@@ -833,8 +836,7 @@ static int kvm_put_vpa(CPUState *cs)
reg.addr = (uintptr_t)&spapr_cpu->dtl_addr;
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to set dispatch trace log state to KVM: %s\n",
- strerror(errno));
+ trace_kvm_failed_dtl_set(strerror(errno));
return ret;
}
@@ -843,7 +845,7 @@ static int kvm_put_vpa(CPUState *cs)
reg.addr = (uintptr_t)&spapr_cpu->vpa_addr;
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
if (ret < 0) {
- DPRINTF("Unable to set VPA address to KVM: %s\n", strerror(errno));
+ trace_kvm_failed_null_vpa_addr_set(strerror(errno));
return ret;
}
}
@@ -929,8 +931,9 @@ int kvm_arch_put_registers(CPUState *cs, int level)
regs.pid = env->spr[SPR_BOOKE_PID];
- for (i = 0;i < 32; i++)
+ for (i = 0; i < 32; i++) {
regs.gpr[i] = env->gpr[i];
+ }
regs.cr = 0;
for (i = 0; i < 8; i++) {
@@ -938,8 +941,9 @@ int kvm_arch_put_registers(CPUState *cs, int level)
}
ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, &regs);
- if (ret < 0)
+ if (ret < 0) {
return ret;
+ }
kvm_put_fp(cs);
@@ -962,10 +966,12 @@ int kvm_arch_put_registers(CPUState *cs, int level)
if (cap_one_reg) {
int i;
- /* We deliberately ignore errors here, for kernels which have
+ /*
+ * We deliberately ignore errors here, for kernels which have
* the ONE_REG calls, but don't support the specific
* registers, there's a reasonable chance things will still
- * work, at least until we try to migrate. */
+ * work, at least until we try to migrate.
+ */
for (i = 0; i < 1024; i++) {
uint64_t id = env->spr_cb[i].one_reg_id;
@@ -996,7 +1002,7 @@ int kvm_arch_put_registers(CPUState *cs, int level)
if (cap_papr) {
if (kvm_put_vpa(cs) < 0) {
- DPRINTF("Warning: Unable to set VPA information to KVM\n");
+ trace_kvm_failed_put_vpa();
}
}
@@ -1207,8 +1213,9 @@ int kvm_arch_get_registers(CPUState *cs)
int i, ret;
ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, &regs);
- if (ret < 0)
+ if (ret < 0) {
return ret;
+ }
cr = regs.cr;
for (i = 7; i >= 0; i--) {
@@ -1236,8 +1243,9 @@ int kvm_arch_get_registers(CPUState *cs)
env->spr[SPR_BOOKE_PID] = regs.pid;
- for (i = 0;i < 32; i++)
+ for (i = 0; i < 32; i++) {
env->gpr[i] = regs.gpr[i];
+ }
kvm_get_fp(cs);
@@ -1262,10 +1270,12 @@ int kvm_arch_get_registers(CPUState *cs)
if (cap_one_reg) {
int i;
- /* We deliberately ignore errors here, for kernels which have
+ /*
+ * We deliberately ignore errors here, for kernels which have
* the ONE_REG calls, but don't support the specific
* registers, there's a reasonable chance things will still
- * work, at least until we try to migrate. */
+ * work, at least until we try to migrate.
+ */
for (i = 0; i < 1024; i++) {
uint64_t id = env->spr_cb[i].one_reg_id;
@@ -1296,7 +1306,7 @@ int kvm_arch_get_registers(CPUState *cs)
if (cap_papr) {
if (kvm_get_vpa(cs) < 0) {
- DPRINTF("Warning: Unable to get VPA information from KVM\n");
+ trace_kvm_failed_get_vpa();
}
}
@@ -1339,20 +1349,24 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
qemu_mutex_lock_iothread();
- /* PowerPC QEMU tracks the various core input pins (interrupt, critical
- * interrupt, reset, etc) in PPC-specific env->irq_input_state. */
+ /*
+ * PowerPC QEMU tracks the various core input pins (interrupt,
+ * critical interrupt, reset, etc) in PPC-specific
+ * env->irq_input_state.
+ */
if (!cap_interrupt_level &&
run->ready_for_interrupt_injection &&
(cs->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->irq_input_state & (1<<PPC_INPUT_INT)))
+ (env->irq_input_state & (1 << PPC_INPUT_INT)))
{
- /* For now KVM disregards the 'irq' argument. However, in the
- * future KVM could cache it in-kernel to avoid a heavyweight exit
- * when reading the UIC.
+ /*
+ * For now KVM disregards the 'irq' argument. However, in the
+ * future KVM could cache it in-kernel to avoid a heavyweight
+ * exit when reading the UIC.
*/
irq = KVM_INTERRUPT_SET;
- DPRINTF("injected interrupt %d\n", irq);
+ trace_kvm_injected_interrupt(irq);
r = kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &irq);
if (r < 0) {
printf("cpu %d fail inject %x\n", cs->cpu_index, irq);
@@ -1363,9 +1377,12 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
(NANOSECONDS_PER_SECOND / 50));
}
- /* We don't know if there are more interrupts pending after this. However,
- * the guest will return to userspace in the course of handling this one
- * anyways, so we will get a chance to deliver the rest. */
+ /*
+ * We don't know if there are more interrupts pending after
+ * this. However, the guest will return to userspace in the course
+ * of handling this one anyways, so we will get a chance to
+ * deliver the rest.
+ */
qemu_mutex_unlock_iothread();
}
@@ -1394,18 +1411,22 @@ static int kvmppc_handle_halt(PowerPCCPU *cpu)
}
/* map dcr access to existing qemu dcr emulation */
-static int kvmppc_handle_dcr_read(CPUPPCState *env, uint32_t dcrn, uint32_t *data)
+static int kvmppc_handle_dcr_read(CPUPPCState *env,
+ uint32_t dcrn, uint32_t *data)
{
- if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0)
+ if (ppc_dcr_read(env->dcr_env, dcrn, data) < 0) {
fprintf(stderr, "Read to unhandled DCR (0x%x)\n", dcrn);
+ }
return 0;
}
-static int kvmppc_handle_dcr_write(CPUPPCState *env, uint32_t dcrn, uint32_t data)
+static int kvmppc_handle_dcr_write(CPUPPCState *env,
+ uint32_t dcrn, uint32_t data)
{
- if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0)
+ if (ppc_dcr_write(env->dcr_env, dcrn, data) < 0) {
fprintf(stderr, "Write to unhandled DCR (0x%x)\n", dcrn);
+ }
return 0;
}
@@ -1697,20 +1718,20 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
switch (run->exit_reason) {
case KVM_EXIT_DCR:
if (run->dcr.is_write) {
- DPRINTF("handle dcr write\n");
+ trace_kvm_handle_dcr_write();
ret = kvmppc_handle_dcr_write(env, run->dcr.dcrn, run->dcr.data);
} else {
- DPRINTF("handle dcr read\n");
+ trace_kvm_handle_drc_read();
ret = kvmppc_handle_dcr_read(env, run->dcr.dcrn, &run->dcr.data);
}
break;
case KVM_EXIT_HLT:
- DPRINTF("handle halt\n");
+ trace_kvm_handle_halt();
ret = kvmppc_handle_halt(cpu);
break;
#if defined(TARGET_PPC64)
case KVM_EXIT_PAPR_HCALL:
- DPRINTF("handle PAPR hypercall\n");
+ trace_kvm_handle_papr_hcall();
run->papr_hcall.ret = spapr_hypercall(cpu,
run->papr_hcall.nr,
run->papr_hcall.args);
@@ -1718,18 +1739,18 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
break;
#endif
case KVM_EXIT_EPR:
- DPRINTF("handle epr\n");
+ trace_kvm_handle_epr();
run->epr.epr = ldl_phys(cs->as, env->mpic_iack);
ret = 0;
break;
case KVM_EXIT_WATCHDOG:
- DPRINTF("handle watchdog expiry\n");
+ trace_kvm_handle_watchdog_expiry();
watchdog_perform_action();
ret = 0;
break;
case KVM_EXIT_DEBUG:
- DPRINTF("handle debug exception\n");
+ trace_kvm_handle_debug_exception();
if (kvm_handle_debug(cpu, run)) {
ret = EXCP_DEBUG;
break;
@@ -1832,7 +1853,7 @@ static int read_cpuinfo(const char *field, char *value, int len)
ret = 0;
break;
}
- } while(*line);
+ } while (*line);
fclose(f);
@@ -1849,7 +1870,8 @@ uint32_t kvmppc_get_tbfreq(void)
return retval;
}
- if (!(ns = strchr(line, ':'))) {
+ ns = strchr(line, ':');
+ if (!ns) {
return retval;
}
@@ -1875,7 +1897,8 @@ static int kvmppc_find_cpu_dt(char *buf, int buf_len)
struct dirent *dirp;
DIR *dp;
- if ((dp = opendir(PROC_DEVTREE_CPU)) == NULL) {
+ dp = opendir(PROC_DEVTREE_CPU);
+ if (!dp) {
printf("Can't open directory " PROC_DEVTREE_CPU "\n");
return -1;
}
@@ -1929,10 +1952,11 @@ static uint64_t kvmppc_read_int_dt(const char *filename)
return 0;
}
-/* Read a CPU node property from the host device tree that's a single
+/*
+ * Read a CPU node property from the host device tree that's a single
* integer (32-bit or 64-bit). Returns 0 if anything goes wrong
- * (can't find or open the property, or doesn't understand the
- * format) */
+ * (can't find or open the property, or doesn't understand the format)
+ */
static uint64_t kvmppc_read_int_cpu_dt(const char *propname)
{
char buf[PATH_MAX], *tmp;
@@ -1991,7 +2015,7 @@ int kvmppc_get_hasidle(CPUPPCState *env)
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
{
- uint32_t *hc = (uint32_t*)buf;
+ uint32_t *hc = (uint32_t *)buf;
struct kvm_ppc_pvinfo pvinfo;
if (!kvmppc_get_pvinfo(env, &pvinfo)) {
@@ -2064,8 +2088,10 @@ void kvmppc_set_papr(PowerPCCPU *cpu)
exit(1);
}
- /* Update the capability flag so we sync the right information
- * with kvm */
+ /*
+ * Update the capability flag so we sync the right information
+ * with kvm
+ */
cap_papr = 1;
}
@@ -2133,10 +2159,12 @@ uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
long rampagesize, best_page_shift;
int i;
- /* Find the largest hardware supported page size that's less than
- * or equal to the (logical) backing page size of guest RAM */
+ /*
+ * Find the largest hardware supported page size that's less than
+ * or equal to the (logical) backing page size of guest RAM
+ */
kvm_get_smmu_info(&info, &error_fatal);
- rampagesize = qemu_getrampagesize();
+ rampagesize = qemu_minrampagesize();
best_page_shift = 0;
for (i = 0; i < KVM_PPC_PAGE_SIZES_MAX_SZ; i++) {
@@ -2184,7 +2212,8 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift,
int fd;
void *table;
- /* Must set fd to -1 so we don't try to munmap when called for
+ /*
+ * Must set fd to -1 so we don't try to munmap when called for
* destroying the table, which the upper layers -will- do
*/
*pfd = -1;
@@ -2229,7 +2258,7 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift,
len = nb_table * sizeof(uint64_t);
/* FIXME: round this up to page size */
- table = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ table = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (table == MAP_FAILED) {
fprintf(stderr, "KVM: Failed to map TCE table for liobn 0x%x\n",
liobn);
@@ -2272,10 +2301,12 @@ int kvmppc_reset_htab(int shift_hint)
int ret;
ret = kvm_vm_ioctl(kvm_state, KVM_PPC_ALLOCATE_HTAB, &shift);
if (ret == -ENOTTY) {
- /* At least some versions of PR KVM advertise the
+ /*
+ * At least some versions of PR KVM advertise the
* capability, but don't implement the ioctl(). Oops.
* Return 0 so that we allocate the htab in qemu, as is
- * correct for PR. */
+ * correct for PR.
+ */
return 0;
} else if (ret < 0) {
return ret;
@@ -2283,9 +2314,12 @@ int kvmppc_reset_htab(int shift_hint)
return shift;
}
- /* We have a kernel that predates the htab reset calls. For PR
+ /*
+ * We have a kernel that predates the htab reset calls. For PR
* KVM, we need to allocate the htab ourselves, for an HV KVM of
- * this era, it has allocated a 16MB fixed size hash table already. */
+ * this era, it has allocated a 16MB fixed size hash table
+ * already.
+ */
if (kvmppc_is_pr(kvm_state)) {
/* PR - tell caller to allocate htab */
return 0;
@@ -2667,8 +2701,8 @@ int kvmppc_save_htab(QEMUFile *f, int fd, size_t bufsize, int64_t max_ns)
}
}
} while ((rc != 0)
- && ((max_ns < 0)
- || ((qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) < max_ns)));
+ && ((max_ns < 0) ||
+ ((qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) < max_ns)));
return (rc == 0) ? 1 : 0;
}
@@ -2677,7 +2711,7 @@ int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index,
uint16_t n_valid, uint16_t n_invalid)
{
struct kvm_get_htab_header *buf;
- size_t chunksize = sizeof(*buf) + n_valid*HASH_PTE_SIZE_64;
+ size_t chunksize = sizeof(*buf) + n_valid * HASH_PTE_SIZE_64;
ssize_t rc;
buf = alloca(chunksize);
@@ -2685,7 +2719,7 @@ int kvmppc_load_htab_chunk(QEMUFile *f, int fd, uint32_t index,
buf->n_valid = n_valid;
buf->n_invalid = n_invalid;
- qemu_get_buffer(f, (void *)(buf + 1), HASH_PTE_SIZE_64*n_valid);
+ qemu_get_buffer(f, (void *)(buf + 1), HASH_PTE_SIZE_64 * n_valid);
rc = write(fd, buf, chunksize);
if (rc < 0) {
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index 2c2ea30e87..22385134b4 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -117,7 +117,8 @@ static inline int kvmppc_get_hasidle(CPUPPCState *env)
return 0;
}
-static inline int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
+static inline int kvmppc_get_hypercall(CPUPPCState *env,
+ uint8_t *buf, int buf_len)
{
return -1;
}
diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index a92d0ad3a3..25cdb9088b 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -24,22 +24,26 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
#endif
target_ulong xer;
- for (i = 0; i < 32; i++)
+ for (i = 0; i < 32; i++) {
qemu_get_betls(f, &env->gpr[i]);
+ }
#if !defined(TARGET_PPC64)
- for (i = 0; i < 32; i++)
+ for (i = 0; i < 32; i++) {
qemu_get_betls(f, &env->gprh[i]);
+ }
#endif
qemu_get_betls(f, &env->lr);
qemu_get_betls(f, &env->ctr);
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++) {
qemu_get_be32s(f, &env->crf[i]);
+ }
qemu_get_betls(f, &xer);
cpu_write_xer(env, xer);
qemu_get_betls(f, &env->reserve_addr);
qemu_get_betls(f, &env->msr);
- for (i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++) {
qemu_get_betls(f, &env->tgpr[i]);
+ }
for (i = 0; i < 32; i++) {
union {
float64 d;
@@ -56,14 +60,19 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
qemu_get_sbe32s(f, &slb_nr);
#endif
qemu_get_betls(f, &sdr1);
- for (i = 0; i < 32; i++)
+ for (i = 0; i < 32; i++) {
qemu_get_betls(f, &env->sr[i]);
- for (i = 0; i < 2; i++)
- for (j = 0; j < 8; j++)
+ }
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 8; j++) {
qemu_get_betls(f, &env->DBAT[i][j]);
- for (i = 0; i < 2; i++)
- for (j = 0; j < 8; j++)
+ }
+ }
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 8; j++) {
qemu_get_betls(f, &env->IBAT[i][j]);
+ }
+ }
qemu_get_sbe32s(f, &env->nb_tlb);
qemu_get_sbe32s(f, &env->tlb_per_way);
qemu_get_sbe32s(f, &env->nb_ways);
@@ -71,17 +80,19 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
qemu_get_sbe32s(f, &env->id_tlbs);
qemu_get_sbe32s(f, &env->nb_pids);
if (env->tlb.tlb6) {
- // XXX assumes 6xx
+ /* XXX assumes 6xx */
for (i = 0; i < env->nb_tlb; i++) {
qemu_get_betls(f, &env->tlb.tlb6[i].pte0);
qemu_get_betls(f, &env->tlb.tlb6[i].pte1);
qemu_get_betls(f, &env->tlb.tlb6[i].EPN);
}
}
- for (i = 0; i < 4; i++)
+ for (i = 0; i < 4; i++) {
qemu_get_betls(f, &env->pb[i]);
- for (i = 0; i < 1024; i++)
+ }
+ for (i = 0; i < 1024; i++) {
qemu_get_betls(f, &env->spr[i]);
+ }
if (!cpu->vhyp) {
ppc_store_sdr1(env, sdr1);
}
@@ -94,8 +105,9 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
qemu_get_sbe32s(f, &env->error_code);
qemu_get_be32s(f, &env->pending_interrupts);
qemu_get_be32s(f, &env->irq_input_state);
- for (i = 0; i < POWERPC_EXCP_NB; i++)
+ for (i = 0; i < POWERPC_EXCP_NB; i++) {
qemu_get_betls(f, &env->excp_vectors[i]);
+ }
qemu_get_betls(f, &env->excp_prefix);
qemu_get_betls(f, &env->ivor_mask);
qemu_get_betls(f, &env->ivpr_mask);
@@ -253,22 +265,24 @@ static int cpu_pre_save(void *opaque)
env->spr[SPR_BOOKE_SPEFSCR] = env->spe_fscr;
for (i = 0; (i < 4) && (i < env->nb_BATs); i++) {
- env->spr[SPR_DBAT0U + 2*i] = env->DBAT[0][i];
- env->spr[SPR_DBAT0U + 2*i + 1] = env->DBAT[1][i];
- env->spr[SPR_IBAT0U + 2*i] = env->IBAT[0][i];
- env->spr[SPR_IBAT0U + 2*i + 1] = env->IBAT[1][i];
+ env->spr[SPR_DBAT0U + 2 * i] = env->DBAT[0][i];
+ env->spr[SPR_DBAT0U + 2 * i + 1] = env->DBAT[1][i];
+ env->spr[SPR_IBAT0U + 2 * i] = env->IBAT[0][i];
+ env->spr[SPR_IBAT0U + 2 * i + 1] = env->IBAT[1][i];
}
- for (i = 0; (i < 4) && ((i+4) < env->nb_BATs); i++) {
- env->spr[SPR_DBAT4U + 2*i] = env->DBAT[0][i+4];
- env->spr[SPR_DBAT4U + 2*i + 1] = env->DBAT[1][i+4];
- env->spr[SPR_IBAT4U + 2*i] = env->IBAT[0][i+4];
- env->spr[SPR_IBAT4U + 2*i + 1] = env->IBAT[1][i+4];
+ for (i = 0; (i < 4) && ((i + 4) < env->nb_BATs); i++) {
+ env->spr[SPR_DBAT4U + 2 * i] = env->DBAT[0][i + 4];
+ env->spr[SPR_DBAT4U + 2 * i + 1] = env->DBAT[1][i + 4];
+ env->spr[SPR_IBAT4U + 2 * i] = env->IBAT[0][i + 4];
+ env->spr[SPR_IBAT4U + 2 * i + 1] = env->IBAT[1][i + 4];
}
/* Hacks for migration compatibility between 2.6, 2.7 & 2.8 */
if (cpu->pre_2_8_migration) {
- /* Mask out bits that got added to msr_mask since the versions
- * which stupidly included it in the migration stream. */
+ /*
+ * Mask out bits that got added to msr_mask since the versions
+ * which stupidly included it in the migration stream.
+ */
target_ulong metamask = 0
#if defined(TARGET_PPC64)
| (1ULL << MSR_TS0)
@@ -277,9 +291,10 @@ static int cpu_pre_save(void *opaque)
;
cpu->mig_msr_mask = env->msr_mask & ~metamask;
cpu->mig_insns_flags = env->insns_flags & insns_compat_mask;
- /* CPU models supported by old machines all have PPC_MEM_TLBIE,
- * so we set it unconditionally to allow backward migration from
- * a POWER9 host to a POWER8 host.
+ /*
+ * CPU models supported by old machines all have
+ * PPC_MEM_TLBIE, so we set it unconditionally to allow
+ * backward migration from a POWER9 host to a POWER8 host.
*/
cpu->mig_insns_flags |= PPC_MEM_TLBIE;
cpu->mig_insns_flags2 = env->insns_flags2 & insns_compat_mask2;
@@ -379,23 +394,26 @@ static int cpu_post_load(void *opaque, int version_id)
env->spe_fscr = env->spr[SPR_BOOKE_SPEFSCR];
for (i = 0; (i < 4) && (i < env->nb_BATs); i++) {
- env->DBAT[0][i] = env->spr[SPR_DBAT0U + 2*i];
- env->DBAT[1][i] = env->spr[SPR_DBAT0U + 2*i + 1];
- env->IBAT[0][i] = env->spr[SPR_IBAT0U + 2*i];
- env->IBAT[1][i] = env->spr[SPR_IBAT0U + 2*i + 1];
+ env->DBAT[0][i] = env->spr[SPR_DBAT0U + 2 * i];
+ env->DBAT[1][i] = env->spr[SPR_DBAT0U + 2 * i + 1];
+ env->IBAT[0][i] = env->spr[SPR_IBAT0U + 2 * i];
+ env->IBAT[1][i] = env->spr[SPR_IBAT0U + 2 * i + 1];
}
- for (i = 0; (i < 4) && ((i+4) < env->nb_BATs); i++) {
- env->DBAT[0][i+4] = env->spr[SPR_DBAT4U + 2*i];
- env->DBAT[1][i+4] = env->spr[SPR_DBAT4U + 2*i + 1];
- env->IBAT[0][i+4] = env->spr[SPR_IBAT4U + 2*i];
- env->IBAT[1][i+4] = env->spr[SPR_IBAT4U + 2*i + 1];
+ for (i = 0; (i < 4) && ((i + 4) < env->nb_BATs); i++) {
+ env->DBAT[0][i + 4] = env->spr[SPR_DBAT4U + 2 * i];
+ env->DBAT[1][i + 4] = env->spr[SPR_DBAT4U + 2 * i + 1];
+ env->IBAT[0][i + 4] = env->spr[SPR_IBAT4U + 2 * i];
+ env->IBAT[1][i + 4] = env->spr[SPR_IBAT4U + 2 * i + 1];
}
if (!cpu->vhyp) {
ppc_store_sdr1(env, env->spr[SPR_SDR1]);
}
- /* Invalidate all supported msr bits except MSR_TGPR/MSR_HVB before restoring */
+ /*
+ * Invalidate all supported msr bits except MSR_TGPR/MSR_HVB
+ * before restoring
+ */
msr = env->msr;
env->msr ^= env->msr_mask & ~((1ULL << MSR_TGPR) | MSR_HVB);
ppc_store_msr(env, msr);
@@ -409,7 +427,7 @@ static bool fpu_needed(void *opaque)
{
PowerPCCPU *cpu = opaque;
- return (cpu->env.insns_flags & PPC_FLOAT);
+ return cpu->env.insns_flags & PPC_FLOAT;
}
static const VMStateDescription vmstate_fpu = {
@@ -428,7 +446,7 @@ static bool altivec_needed(void *opaque)
{
PowerPCCPU *cpu = opaque;
- return (cpu->env.insns_flags & PPC_ALTIVEC);
+ return cpu->env.insns_flags & PPC_ALTIVEC;
}
static int get_vscr(QEMUFile *f, void *opaque, size_t size,
@@ -483,7 +501,7 @@ static bool vsx_needed(void *opaque)
{
PowerPCCPU *cpu = opaque;
- return (cpu->env.insns_flags2 & PPC2_VSX);
+ return cpu->env.insns_flags2 & PPC2_VSX;
}
static const VMStateDescription vmstate_vsx = {
@@ -591,7 +609,7 @@ static bool slb_needed(void *opaque)
PowerPCCPU *cpu = opaque;
/* We don't support any of the old segment table based 64-bit CPUs */
- return (cpu->env.mmu_model & POWERPC_MMU_64);
+ return cpu->env.mmu_model & POWERPC_MMU_64;
}
static int slb_post_load(void *opaque, int version_id)
@@ -600,8 +618,10 @@ static int slb_post_load(void *opaque, int version_id)
CPUPPCState *env = &cpu->env;
int i;
- /* We've pulled in the raw esid and vsid values from the migration
- * stream, but we need to recompute the page size pointers */
+ /*
+ * We've pulled in the raw esid and vsid values from the migration
+ * stream, but we need to recompute the page size pointers
+ */
for (i = 0; i < cpu->hash64_opts->slb_size; i++) {
if (ppc_store_slb(cpu, i, env->slb[i].esid, env->slb[i].vsid) < 0) {
/* Migration source had bad values in its SLB */
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c
index 9c5a68579e..5b0f9ee50d 100644
--- a/target/ppc/mem_helper.c
+++ b/target/ppc/mem_helper.c
@@ -27,7 +27,7 @@
#include "internal.h"
#include "qemu/atomic128.h"
-//#define DEBUG_OP
+/* #define DEBUG_OP */
static inline bool needs_byteswap(const CPUPPCState *env)
{
@@ -103,10 +103,11 @@ void helper_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb, uint32_t reg)
do_lsw(env, addr, nb, reg, GETPC());
}
-/* PPC32 specification says we must generate an exception if
- * rA is in the range of registers to be loaded.
- * In an other hand, IBM says this is valid, but rA won't be loaded.
- * For now, I'll follow the spec...
+/*
+ * PPC32 specification says we must generate an exception if rA is in
+ * the range of registers to be loaded. In an other hand, IBM says
+ * this is valid, but rA won't be loaded. For now, I'll follow the
+ * spec...
*/
void helper_lswx(CPUPPCState *env, target_ulong addr, uint32_t reg,
uint32_t ra, uint32_t rb)
@@ -199,7 +200,8 @@ void helper_dcbzep(CPUPPCState *env, target_ulong addr, uint32_t opcode)
void helper_icbi(CPUPPCState *env, target_ulong addr)
{
addr &= ~(env->dcache_line_size - 1);
- /* Invalidate one cache line :
+ /*
+ * Invalidate one cache line :
* PowerPC specification says this is to be treated like a load
* (not a fetch) by the MMU. To be sure it will be so,
* do the load "by hand".
@@ -346,17 +348,19 @@ uint32_t helper_stqcx_be_parallel(CPUPPCState *env, target_ulong addr,
#define LO_IDX 0
#endif
-/* We use msr_le to determine index ordering in a vector. However,
- byteswapping is not simply controlled by msr_le. We also need to take
- into account endianness of the target. This is done for the little-endian
- PPC64 user-mode target. */
+/*
+ * We use msr_le to determine index ordering in a vector. However,
+ * byteswapping is not simply controlled by msr_le. We also need to
+ * take into account endianness of the target. This is done for the
+ * little-endian PPC64 user-mode target.
+ */
#define LVE(name, access, swap, element) \
void helper_##name(CPUPPCState *env, ppc_avr_t *r, \
target_ulong addr) \
{ \
size_t n_elems = ARRAY_SIZE(r->element); \
- int adjust = HI_IDX*(n_elems - 1); \
+ int adjust = HI_IDX * (n_elems - 1); \
int sh = sizeof(r->element[0]) >> 1; \
int index = (addr & 0xf) >> sh; \
if (msr_le) { \
@@ -476,12 +480,13 @@ VSX_STXVL(stxvll, 1)
void helper_tbegin(CPUPPCState *env)
{
- /* As a degenerate implementation, always fail tbegin. The reason
+ /*
+ * As a degenerate implementation, always fail tbegin. The reason
* given is "Nesting overflow". The "persistent" bit is set,
* providing a hint to the error handler to not retry. The TFIAR
* captures the address of the failure, which is this tbegin
- * instruction. Instruction execution will continue with the
- * next instruction in memory, which is precisely what we want.
+ * instruction. Instruction execution will continue with the next
+ * instruction in memory, which is precisely what we want.
*/
env->spr[SPR_TEXASR] =
diff --git a/target/ppc/mfrom_table.inc.c b/target/ppc/mfrom_table.inc.c
index 6a1fa375c9..1653b974a4 100644
--- a/target/ppc/mfrom_table.inc.c
+++ b/target/ppc/mfrom_table.inc.c
@@ -1,5 +1,4 @@
-static const uint8_t mfrom_ROM_table[602] =
-{
+static const uint8_t mfrom_ROM_table[602] = {
77, 77, 76, 76, 75, 75, 74, 74,
73, 73, 72, 72, 71, 71, 70, 70,
69, 69, 68, 68, 68, 67, 67, 66,
diff --git a/target/ppc/mfrom_table_gen.c b/target/ppc/mfrom_table_gen.c
index 631791808e..f96c4268ba 100644
--- a/target/ppc/mfrom_table_gen.c
+++ b/target/ppc/mfrom_table_gen.c
@@ -2,7 +2,7 @@
#include "qemu/osdep.h"
#include <math.h>
-int main (void)
+int main(void)
{
double d;
uint8_t n;
@@ -10,7 +10,8 @@ int main (void)
printf("static const uint8_t mfrom_ROM_table[602] =\n{\n ");
for (i = 0; i < 602; i++) {
- /* Extremely decomposed:
+ /*
+ * Extremely decomposed:
* -T0 / 256
* T0 = 256 * log10(10 + 1.0) + 0.5
*/
@@ -23,8 +24,9 @@ int main (void)
d += 0.5;
n = d;
printf("%3d, ", n);
- if ((i & 7) == 7)
+ if ((i & 7) == 7) {
printf("\n ");
+ }
}
printf("\n};\n");
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index c65d1ade15..0a81e98ee9 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -210,10 +210,11 @@ void ppc_store_msr(CPUPPCState *env, target_ulong value)
hreg_store_msr(env, value, 0);
}
-/* This code is lifted from MacOnLinux. It is called whenever
- * THRM1,2 or 3 is read an fixes up the values in such a way
- * that will make MacOS not hang. These registers exist on some
- * 75x and 74xx processors.
+/*
+ * This code is lifted from MacOnLinux. It is called whenever THRM1,2
+ * or 3 is read an fixes up the values in such a way that will make
+ * MacOS not hang. These registers exist on some 75x and 74xx
+ * processors.
*/
void helper_fixup_thrm(CPUPPCState *env)
{
diff --git a/target/ppc/mmu-hash32.c b/target/ppc/mmu-hash32.c
index e8562a7c87..55cf156a0b 100644
--- a/target/ppc/mmu-hash32.c
+++ b/target/ppc/mmu-hash32.c
@@ -27,7 +27,7 @@
#include "mmu-hash32.h"
#include "exec/log.h"
-//#define DEBUG_BAT
+/* #define DEBUG_BAT */
#ifdef DEBUG_BATS
# define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
@@ -228,8 +228,10 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
if ((sr & 0x1FF00000) >> 20 == 0x07f) {
- /* Memory-forced I/O controller interface access */
- /* If T=1 and BUID=x'07F', the 601 performs a memory access
+ /*
+ * Memory-forced I/O controller interface access
+ *
+ * If T=1 and BUID=x'07F', the 601 performs a memory access
* to SR[28-31] LA[4-31], bypassing all protection mechanisms.
*/
*raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
@@ -265,9 +267,11 @@ static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
}
return 1;
case ACCESS_CACHE:
- /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
- /* Should make the instruction do no-op.
- * As it already do no-op, it's quite easy :-)
+ /*
+ * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
+ *
+ * Should make the instruction do no-op. As it already do
+ * no-op, it's quite easy :-)
*/
*raddr = eaddr;
return 0;
@@ -341,6 +345,24 @@ static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pteg_off,
return -1;
}
+static void ppc_hash32_set_r(PowerPCCPU *cpu, hwaddr pte_offset, uint32_t pte1)
+{
+ target_ulong base = ppc_hash32_hpt_base(cpu);
+ hwaddr offset = pte_offset + 6;
+
+ /* The HW performs a non-atomic byte update */
+ stb_phys(CPU(cpu)->as, base + offset, ((pte1 >> 8) & 0xff) | 0x01);
+}
+
+static void ppc_hash32_set_c(PowerPCCPU *cpu, hwaddr pte_offset, uint64_t pte1)
+{
+ target_ulong base = ppc_hash32_hpt_base(cpu);
+ hwaddr offset = pte_offset + 7;
+
+ /* The HW performs a non-atomic byte update */
+ stb_phys(CPU(cpu)->as, base + offset, (pte1 & 0xff) | 0x80);
+}
+
static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
target_ulong sr, target_ulong eaddr,
ppc_hash_pte32_t *pte)
@@ -399,7 +421,6 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
hwaddr pte_offset;
ppc_hash_pte32_t pte;
int prot;
- uint32_t new_pte1;
const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
hwaddr raddr;
@@ -515,18 +536,20 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
/* 8. Update PTE referenced and changed bits if necessary */
- new_pte1 = pte.pte1 | HPTE32_R_R; /* set referenced bit */
- if (rwx == 1) {
- new_pte1 |= HPTE32_R_C; /* set changed (dirty) bit */
- } else {
- /* Treat the page as read-only for now, so that a later write
- * will pass through this function again to set the C bit */
- prot &= ~PAGE_WRITE;
- }
-
- if (new_pte1 != pte.pte1) {
- ppc_hash32_store_hpte1(cpu, pte_offset, new_pte1);
+ if (!(pte.pte1 & HPTE32_R_R)) {
+ ppc_hash32_set_r(cpu, pte_offset, pte.pte1);
}
+ if (!(pte.pte1 & HPTE32_R_C)) {
+ if (rwx == 1) {
+ ppc_hash32_set_c(cpu, pte_offset, pte.pte1);
+ } else {
+ /*
+ * Treat the page as read-only for now, so that a later write
+ * will pass through this function again to set the C bit
+ */
+ prot &= ~PAGE_WRITE;
+ }
+ }
/* 9. Determine the real address from the PTE */
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index 214149f65b..7899eb2918 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -30,7 +30,7 @@
#include "hw/hw.h"
#include "mmu-book3s-v3.h"
-//#define DEBUG_SLB
+/* #define DEBUG_SLB */
#ifdef DEBUG_SLB
# define LOG_SLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
@@ -58,9 +58,11 @@ static ppc_slb_t *slb_lookup(PowerPCCPU *cpu, target_ulong eaddr)
LOG_SLB("%s: slot %d %016" PRIx64 " %016"
PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
- /* We check for 1T matches on all MMUs here - if the MMU
+ /*
+ * We check for 1T matches on all MMUs here - if the MMU
* doesn't have 1T segment support, we will have prevented 1T
- * entries from being inserted in the slbmte code. */
+ * entries from being inserted in the slbmte code.
+ */
if (((slb->esid == esid_256M) &&
((slb->vsid & SLB_VSID_B) == SLB_VSID_B_256M))
|| ((slb->esid == esid_1T) &&
@@ -103,7 +105,8 @@ void helper_slbia(CPUPPCState *env)
if (slb->esid & SLB_ESID_V) {
slb->esid &= ~SLB_ESID_V;
- /* XXX: given the fact that segment size is 256 MB or 1TB,
+ /*
+ * XXX: given the fact that segment size is 256 MB or 1TB,
* and we still don't have a tlb_flush_mask(env, n, mask)
* in QEMU, we just invalidate all TLBs
*/
@@ -126,7 +129,8 @@ static void __helper_slbie(CPUPPCState *env, target_ulong addr,
if (slb->esid & SLB_ESID_V) {
slb->esid &= ~SLB_ESID_V;
- /* XXX: given the fact that segment size is 256 MB or 1TB,
+ /*
+ * XXX: given the fact that segment size is 256 MB or 1TB,
* and we still don't have a tlb_flush_mask(env, n, mask)
* in QEMU, we just invalidate all TLBs
*/
@@ -306,8 +310,10 @@ static int ppc_hash64_pte_prot(PowerPCCPU *cpu,
{
CPUPPCState *env = &cpu->env;
unsigned pp, key;
- /* Some pp bit combinations have undefined behaviour, so default
- * to no access in those cases */
+ /*
+ * Some pp bit combinations have undefined behaviour, so default
+ * to no access in those cases
+ */
int prot = 0;
key = !!(msr_pr ? (slb->vsid & SLB_VSID_KP)
@@ -376,7 +382,7 @@ static int ppc_hash64_amr_prot(PowerPCCPU *cpu, ppc_hash_pte64_t pte)
}
key = HPTE64_R_KEY(pte.pte1);
- amrbits = (env->spr[SPR_AMR] >> 2*(31 - key)) & 0x3;
+ amrbits = (env->spr[SPR_AMR] >> 2 * (31 - key)) & 0x3;
/* fprintf(stderr, "AMR protection: key=%d AMR=0x%" PRIx64 "\n", key, */
/* env->spr[SPR_AMR]); */
@@ -547,8 +553,9 @@ static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash,
if (*pshift == 0) {
continue;
}
- /* We don't do anything with pshift yet as qemu TLB only deals
- * with 4K pages anyway
+ /*
+ * We don't do anything with pshift yet as qemu TLB only
+ * deals with 4K pages anyway
*/
pte->pte0 = pte0;
pte->pte1 = pte1;
@@ -572,8 +579,10 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu,
uint64_t vsid, epnmask, epn, ptem;
const PPCHash64SegmentPageSizes *sps = slb->sps;
- /* The SLB store path should prevent any bad page size encodings
- * getting in there, so: */
+ /*
+ * The SLB store path should prevent any bad page size encodings
+ * getting in there, so:
+ */
assert(sps);
/* If ISL is set in LPCR we need to clamp the page size to 4K */
@@ -716,6 +725,39 @@ static void ppc_hash64_set_dsi(CPUState *cs, uint64_t dar, uint64_t dsisr)
}
+static void ppc_hash64_set_r(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1)
+{
+ hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 16;
+
+ if (cpu->vhyp) {
+ PPCVirtualHypervisorClass *vhc =
+ PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ vhc->hpte_set_r(cpu->vhyp, ptex, pte1);
+ return;
+ }
+ base = ppc_hash64_hpt_base(cpu);
+
+
+ /* The HW performs a non-atomic byte update */
+ stb_phys(CPU(cpu)->as, base + offset, ((pte1 >> 8) & 0xff) | 0x01);
+}
+
+static void ppc_hash64_set_c(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1)
+{
+ hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 15;
+
+ if (cpu->vhyp) {
+ PPCVirtualHypervisorClass *vhc =
+ PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
+ vhc->hpte_set_c(cpu->vhyp, ptex, pte1);
+ return;
+ }
+ base = ppc_hash64_hpt_base(cpu);
+
+ /* The HW performs a non-atomic byte update */
+ stb_phys(CPU(cpu)->as, base + offset, (pte1 & 0xff) | 0x80);
+}
+
int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
int rwx, int mmu_idx)
{
@@ -726,23 +768,25 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
hwaddr ptex;
ppc_hash_pte64_t pte;
int exec_prot, pp_prot, amr_prot, prot;
- uint64_t new_pte1;
const int need_prot[] = {PAGE_READ, PAGE_WRITE, PAGE_EXEC};
hwaddr raddr;
assert((rwx == 0) || (rwx == 1) || (rwx == 2));
- /* Note on LPCR usage: 970 uses HID4, but our special variant
- * of store_spr copies relevant fields into env->spr[SPR_LPCR].
- * Similarily we filter unimplemented bits when storing into
- * LPCR depending on the MMU version. This code can thus just
- * use the LPCR "as-is".
+ /*
+ * Note on LPCR usage: 970 uses HID4, but our special variant of
+ * store_spr copies relevant fields into env->spr[SPR_LPCR].
+ * Similarily we filter unimplemented bits when storing into LPCR
+ * depending on the MMU version. This code can thus just use the
+ * LPCR "as-is".
*/
/* 1. Handle real mode accesses */
if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
- /* Translation is supposedly "off" */
- /* In real mode the top 4 effective address bits are (mostly) ignored */
+ /*
+ * Translation is supposedly "off", but in real mode the top 4
+ * effective address bits are (mostly) ignored
+ */
raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
/* In HV mode, add HRMOR if top EA bit is clear */
@@ -871,17 +915,19 @@ skip_slb_search:
/* 6. Update PTE referenced and changed bits if necessary */
- new_pte1 = pte.pte1 | HPTE64_R_R; /* set referenced bit */
- if (rwx == 1) {
- new_pte1 |= HPTE64_R_C; /* set changed (dirty) bit */
- } else {
- /* Treat the page as read-only for now, so that a later write
- * will pass through this function again to set the C bit */
- prot &= ~PAGE_WRITE;
+ if (!(pte.pte1 & HPTE64_R_R)) {
+ ppc_hash64_set_r(cpu, ptex, pte.pte1);
}
-
- if (new_pte1 != pte.pte1) {
- ppc_hash64_store_hpte(cpu, ptex, pte.pte0, new_pte1);
+ if (!(pte.pte1 & HPTE64_R_C)) {
+ if (rwx == 1) {
+ ppc_hash64_set_c(cpu, ptex, pte.pte1);
+ } else {
+ /*
+ * Treat the page as read-only for now, so that a later write
+ * will pass through this function again to set the C bit
+ */
+ prot &= ~PAGE_WRITE;
+ }
}
/* 7. Determine the real address from the PTE */
@@ -940,24 +986,6 @@ hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr)
& TARGET_PAGE_MASK;
}
-void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
- uint64_t pte0, uint64_t pte1)
-{
- hwaddr base;
- hwaddr offset = ptex * HASH_PTE_SIZE_64;
-
- if (cpu->vhyp) {
- PPCVirtualHypervisorClass *vhc =
- PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
- vhc->store_hpte(cpu->vhyp, ptex, pte0, pte1);
- return;
- }
- base = ppc_hash64_hpt_base(cpu);
-
- stq_phys(CPU(cpu)->as, base + offset, pte0);
- stq_phys(CPU(cpu)->as, base + offset + HASH_PTE_SIZE_64 / 2, pte1);
-}
-
void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong ptex,
target_ulong pte0, target_ulong pte1)
{
@@ -1023,8 +1051,9 @@ static void ppc_hash64_update_vrma(PowerPCCPU *cpu)
return;
}
- /* Make one up. Mostly ignore the ESID which will not be
- * needed for translation
+ /*
+ * Make one up. Mostly ignore the ESID which will not be needed
+ * for translation
*/
vsid = SLB_VSID_VRMA;
vrmasd = (lpcr & LPCR_VRMASD) >> LPCR_VRMASD_SHIFT;
@@ -1080,11 +1109,12 @@ void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)
}
env->spr[SPR_RMOR] = ((lpcr >> 41) & 0xffffull) << 26;
- /* XXX We could also write LPID from HID4 here
+ /*
+ * XXX We could also write LPID from HID4 here
* but since we don't tag any translation on it
* it doesn't actually matter
- */
- /* XXX For proper emulation of 970 we also need
+ *
+ * XXX For proper emulation of 970 we also need
* to dig HRMOR out of HID5
*/
break;
diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h
index 5be7ad86db..87729d48b3 100644
--- a/target/ppc/mmu-hash64.h
+++ b/target/ppc/mmu-hash64.h
@@ -10,8 +10,6 @@ int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot,
hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr);
int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr address, int rw,
int mmu_idx);
-void ppc_hash64_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
- uint64_t pte0, uint64_t pte1);
void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu,
target_ulong pte_index,
target_ulong pte0, target_ulong pte1);
diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c
index ca1fb2673f..066e324464 100644
--- a/target/ppc/mmu-radix64.c
+++ b/target/ppc/mmu-radix64.c
@@ -228,10 +228,10 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
ppc_v3_pate_t pate;
assert((rwx == 0) || (rwx == 1) || (rwx == 2));
- assert(ppc64_use_proc_tbl(cpu));
- /* Real Mode Access */
- if (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0))) {
+ /* HV or virtual hypervisor Real Mode Access */
+ if ((msr_hv || cpu->vhyp) &&
+ (((rwx == 2) && (msr_ir == 0)) || ((rwx != 2) && (msr_dr == 0)))) {
/* In real mode top 4 effective addr bits (mostly) ignored */
raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
@@ -241,6 +241,16 @@ int ppc_radix64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr, int rwx,
return 0;
}
+ /*
+ * Check UPRT (we avoid the check in real mode to deal with
+ * transitional states during kexec.
+ */
+ if (!ppc64_use_proc_tbl(cpu)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "LPCR:UPRT not set in radix mode ! LPCR="
+ TARGET_FMT_lx "\n", env->spr[SPR_LPCR]);
+ }
+
/* Virtual Mode Access - get the fully qualified address */
if (!ppc_radix64_get_fully_qualified_addr(env, eaddr, &lpid, &pid)) {
ppc_radix64_raise_segi(cpu, rwx, eaddr);
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index ab72473eeb..1dbc9acb75 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -33,11 +33,11 @@
#include "mmu-book3s-v3.h"
#include "mmu-radix64.h"
-//#define DEBUG_MMU
-//#define DEBUG_BATS
-//#define DEBUG_SOFTWARE_TLB
-//#define DUMP_PAGE_TABLES
-//#define FLUSH_ALL_TLBS
+/* #define DEBUG_MMU */
+/* #define DEBUG_BATS */
+/* #define DEBUG_SOFTWARE_TLB */
+/* #define DUMP_PAGE_TABLES */
+/* #define FLUSH_ALL_TLBS */
#ifdef DEBUG_MMU
# define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0)
@@ -152,7 +152,8 @@ static int check_prot(int prot, int rw, int access_type)
}
static inline int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
- target_ulong pte1, int h, int rw, int type)
+ target_ulong pte1, int h,
+ int rw, int type)
{
target_ulong ptem, mmask;
int access, ret, pteh, ptev, pp;
@@ -332,7 +333,8 @@ static inline int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
pte_is_valid(tlb->pte0) ? "valid" : "inval",
tlb->EPN, eaddr, tlb->pte1,
rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
- switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
+ switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1,
+ 0, rw, access_type)) {
case -3:
/* TLB inconsistency */
return -1;
@@ -347,9 +349,11 @@ static inline int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
break;
case 0:
/* access granted */
- /* XXX: we should go on looping to check all TLBs consistency
- * but we can speed-up the whole thing as the
- * result would be undefined if TLBs are not consistent.
+ /*
+ * XXX: we should go on looping to check all TLBs
+ * consistency but we can speed-up the whole thing as
+ * the result would be undefined if TLBs are not
+ * consistent.
*/
ret = 0;
best = nr;
@@ -550,14 +554,18 @@ static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
/* Direct-store segment : absolutely *BUGGY* for now */
- /* Direct-store implies a 32-bit MMU.
+ /*
+ * Direct-store implies a 32-bit MMU.
* Check the Segment Register's bus unit ID (BUID).
*/
sr = env->sr[eaddr >> 28];
if ((sr & 0x1FF00000) >> 20 == 0x07f) {
- /* Memory-forced I/O controller interface access */
- /* If T=1 and BUID=x'07F', the 601 performs a memory access
- * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
+ /*
+ * Memory-forced I/O controller interface access
+ *
+ * If T=1 and BUID=x'07F', the 601 performs a memory
+ * access to SR[28-31] LA[4-31], bypassing all protection
+ * mechanisms.
*/
ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
@@ -578,9 +586,11 @@ static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
/* lwarx, ldarx or srwcx. */
return -4;
case ACCESS_CACHE:
- /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
- /* Should make the instruction do no-op.
- * As it already do no-op, it's quite easy :-)
+ /*
+ * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
+ *
+ * Should make the instruction do no-op. As it already do
+ * no-op, it's quite easy :-)
*/
ctx->raddr = eaddr;
return 0;
@@ -942,12 +952,14 @@ static uint32_t mmubooke206_esr(int mmu_idx, bool rw)
return esr;
}
-/* Get EPID register given the mmu_idx. If this is regular load,
- * construct the EPID access bits from current processor state */
-
-/* Get the effective AS and PR bits and the PID. The PID is returned only if
- * EPID load is requested, otherwise the caller must detect the correct EPID.
- * Return true if valid EPID is returned. */
+/*
+ * Get EPID register given the mmu_idx. If this is regular load,
+ * construct the EPID access bits from current processor state
+ *
+ * Get the effective AS and PR bits and the PID. The PID is returned
+ * only if EPID load is requested, otherwise the caller must detect
+ * the correct EPID. Return true if valid EPID is returned.
+ */
static bool mmubooke206_get_as(CPUPPCState *env,
int mmu_idx, uint32_t *epid_out,
bool *as_out, bool *pr_out)
@@ -1369,8 +1381,9 @@ static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
case POWERPC_MMU_SOFT_4xx_Z:
if (unlikely(msr_pe != 0)) {
- /* 403 family add some particular protections,
- * using PBL/PBU registers for accesses with no translation.
+ /*
+ * 403 family add some particular protections, using
+ * PBL/PBU registers for accesses with no translation.
*/
in_plb =
/* Check PLB validity */
@@ -1453,7 +1466,8 @@ static int get_physical_address_wtlb(
if (real_mode) {
ret = check_physical(env, ctx, eaddr, rw);
} else {
- cpu_abort(CPU(cpu), "PowerPC in real mode do not do any translation\n");
+ cpu_abort(CPU(cpu),
+ "PowerPC in real mode do not do any translation\n");
}
return -1;
default:
@@ -1498,9 +1512,10 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0)) {
- /* Some MMUs have separate TLBs for code and data. If we only try an
- * ACCESS_INT, we may not be able to read instructions mapped by code
- * TLBs, so we also try a ACCESS_CODE.
+ /*
+ * Some MMUs have separate TLBs for code and data. If we only
+ * try an ACCESS_INT, we may not be able to read instructions
+ * mapped by code TLBs, so we also try a ACCESS_CODE.
*/
if (unlikely(get_physical_address(env, &ctx, addr, 0,
ACCESS_CODE) != 0)) {
@@ -1805,6 +1820,13 @@ static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
base = BATu & ~0x0001FFFF;
end = base + mask + 0x00020000;
+ if (((end - base) >> TARGET_PAGE_BITS) > 1024) {
+ /* Flushing 1024 4K pages is slower than a complete flush */
+ LOG_BATS("Flush all BATs\n");
+ tlb_flush(CPU(cs));
+ LOG_BATS("Flush done\n");
+ return;
+ }
LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
TARGET_FMT_lx ")\n", base, end, mask);
for (page = base; page != end; page += TARGET_PAGE_SIZE) {
@@ -1834,8 +1856,9 @@ void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value)
#if !defined(FLUSH_ALL_TLBS)
do_invalidate_BAT(env, env->IBAT[0][nr], mask);
#endif
- /* When storing valid upper BAT, mask BEPI and BRPN
- * and invalidate all TLBs covered by this BAT
+ /*
+ * When storing valid upper BAT, mask BEPI and BRPN and
+ * invalidate all TLBs covered by this BAT
*/
mask = (value << 15) & 0x0FFE0000UL;
env->IBAT[0][nr] = (value & 0x00001FFFUL) |
@@ -1865,8 +1888,9 @@ void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value)
dump_store_bat(env, 'D', 0, nr, value);
if (env->DBAT[0][nr] != value) {
- /* When storing valid upper BAT, mask BEPI and BRPN
- * and invalidate all TLBs covered by this BAT
+ /*
+ * When storing valid upper BAT, mask BEPI and BRPN and
+ * invalidate all TLBs covered by this BAT
*/
mask = (value << 15) & 0x0FFE0000UL;
#if !defined(FLUSH_ALL_TLBS)
@@ -1913,8 +1937,9 @@ void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
do_inval = 1;
#endif
}
- /* When storing valid upper BAT, mask BEPI and BRPN
- * and invalidate all TLBs covered by this BAT
+ /*
+ * When storing valid upper BAT, mask BEPI and BRPN and
+ * invalidate all TLBs covered by this BAT
*/
env->IBAT[0][nr] = (value & 0x00001FFFUL) |
(value & ~0x0001FFFFUL & ~mask);
@@ -2027,7 +2052,8 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
#if defined(TARGET_PPC64)
if (env->mmu_model & POWERPC_MMU_64) {
/* tlbie invalidate TLBs for all segments */
- /* XXX: given the fact that there are too many segments to invalidate,
+ /*
+ * XXX: given the fact that there are too many segments to invalidate,
* and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
* we just invalidate all TLBs
*/
@@ -2044,10 +2070,11 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
break;
case POWERPC_MMU_32B:
case POWERPC_MMU_601:
- /* Actual CPUs invalidate entire congruence classes based on the
- * geometry of their TLBs and some OSes take that into account,
- * we just mark the TLB to be flushed later (context synchronizing
- * event or sync instruction on 32-bit).
+ /*
+ * Actual CPUs invalidate entire congruence classes based on
+ * the geometry of their TLBs and some OSes take that into
+ * account, we just mark the TLB to be flushed later (context
+ * synchronizing event or sync instruction on 32-bit).
*/
env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
break;
@@ -2152,8 +2179,10 @@ void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
#endif
if (env->sr[srnum] != value) {
env->sr[srnum] = value;
-/* Invalidating 256MB of virtual memory in 4kB pages is way longer than
- flusing the whole TLB. */
+ /*
+ * Invalidating 256MB of virtual memory in 4kB pages is way
+ * longer than flusing the whole TLB.
+ */
#if !defined(FLUSH_ALL_TLBS) && 0
{
target_ulong page, end;
@@ -2264,10 +2293,12 @@ target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
int nb_BATs;
target_ulong ret = 0;
- /* We don't have to generate many instances of this instruction,
+ /*
+ * We don't have to generate many instances of this instruction,
* as rac is supervisor only.
+ *
+ * XXX: FIX THIS: Pretend we have no BAT
*/
- /* XXX: FIX THIS: Pretend we have no BAT */
nb_BATs = env->nb_BATs;
env->nb_BATs = 0;
if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) {
@@ -2422,7 +2453,8 @@ void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,
}
tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT)
& PPC4XX_TLBHI_SIZE_MASK);
- /* We cannot handle TLB size < TARGET_PAGE_SIZE.
+ /*
+ * We cannot handle TLB size < TARGET_PAGE_SIZE.
* If this ever occurs, we should implement TARGET_PAGE_BITS_VARY
*/
if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) {
@@ -2742,7 +2774,8 @@ void helper_booke206_tlbwe(CPUPPCState *env)
}
if (tlb->mas1 & MAS1_VALID) {
- /* Invalidate the page in QEMU TLB if it was a valid entry.
+ /*
+ * Invalidate the page in QEMU TLB if it was a valid entry.
*
* In "PowerPC e500 Core Family Reference Manual, Rev. 1",
* Section "12.4.2 TLB Write Entry (tlbwe) Instruction":
@@ -2751,7 +2784,8 @@ void helper_booke206_tlbwe(CPUPPCState *env)
* "Note that when an L2 TLB entry is written, it may be displacing an
* already valid entry in the same L2 TLB location (a victim). If a
* valid L1 TLB entry corresponds to the L2 MMU victim entry, that L1
- * TLB entry is automatically invalidated." */
+ * TLB entry is automatically invalidated."
+ */
flush_page(env, tlb);
}
@@ -2777,8 +2811,9 @@ void helper_booke206_tlbwe(CPUPPCState *env)
mask |= MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E;
if (!msr_cm) {
- /* Executing a tlbwe instruction in 32-bit mode will set
- * bits 0:31 of the TLB EPN field to zero.
+ /*
+ * Executing a tlbwe instruction in 32-bit mode will set bits
+ * 0:31 of the TLB EPN field to zero.
*/
mask &= 0xffffffff;
}
@@ -3022,10 +3057,13 @@ void helper_check_tlb_flush_global(CPUPPCState *env)
/*****************************************************************************/
-/* try to fill the TLB and return an exception if error. If retaddr is
- NULL, it means that the function was called in C code (i.e. not
- from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
+/*
+ * try to fill the TLB and return an exception if error. If retaddr is
+ * NULL, it means that the function was called in C code (i.e. not
+ * from generated code or from helper.c)
+ *
+ * XXX: fix it to restore all registers
+ */
void tlb_fill(CPUState *cs, target_ulong addr, int size,
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
{
diff --git a/target/ppc/monitor.c b/target/ppc/monitor.c
index 42e58163fc..ee9d6e81d2 100644
--- a/target/ppc/monitor.c
+++ b/target/ppc/monitor.c
@@ -27,32 +27,33 @@
#include "monitor/hmp-target.h"
#include "hmp.h"
-static target_long monitor_get_ccr (const struct MonitorDef *md, int val)
+static target_long monitor_get_ccr(const struct MonitorDef *md, int val)
{
CPUArchState *env = mon_get_cpu_env();
unsigned int u;
int i;
u = 0;
- for (i = 0; i < 8; i++)
+ for (i = 0; i < 8; i++) {
u |= env->crf[i] << (32 - (4 * (i + 1)));
+ }
return u;
}
-static target_long monitor_get_decr (const struct MonitorDef *md, int val)
+static target_long monitor_get_decr(const struct MonitorDef *md, int val)
{
CPUArchState *env = mon_get_cpu_env();
return cpu_ppc_load_decr(env);
}
-static target_long monitor_get_tbu (const struct MonitorDef *md, int val)
+static target_long monitor_get_tbu(const struct MonitorDef *md, int val)
{
CPUArchState *env = mon_get_cpu_env();
return cpu_ppc_load_tbu(env);
}
-static target_long monitor_get_tbl (const struct MonitorDef *md, int val)
+static target_long monitor_get_tbl(const struct MonitorDef *md, int val)
{
CPUArchState *env = mon_get_cpu_env();
return cpu_ppc_load_tbl(env);
diff --git a/target/ppc/trace-events b/target/ppc/trace-events
index 3858f97dff..7b3cfe11fd 100644
--- a/target/ppc/trace-events
+++ b/target/ppc/trace-events
@@ -1,5 +1,30 @@
# See docs/devel/tracing.txt for syntax documentation.
# kvm.c
-kvm_failed_spr_set(int str, const char *msg) "Warning: Unable to set SPR %d to KVM: %s"
-kvm_failed_spr_get(int str, const char *msg) "Warning: Unable to retrieve SPR %d from KVM: %s"
+kvm_failed_spr_set(int spr, const char *msg) "Warning: Unable to set SPR %d to KVM: %s"
+kvm_failed_spr_get(int spr, const char *msg) "Warning: Unable to retrieve SPR %d from KVM: %s"
+kvm_failed_fpscr_set(const char *msg) "Unable to set FPSCR to KVM: %s"
+kvm_failed_fp_set(const char *fpname, int fpnum, const char *msg) "Unable to set %s%d to KVM: %s"
+kvm_failed_vscr_set(const char *msg) "Unable to set VSCR to KVM: %s"
+kvm_failed_vr_set(int vr, const char *msg) "Unable to set VR%d to KVM: %s"
+kvm_failed_fpscr_get(const char *msg) "Unable to get FPSCR from KVM: %s"
+kvm_failed_fp_get(const char *fpname, int fpnum, const char *msg) "Unable to get %s%d from KVM: %s"
+kvm_failed_vscr_get(const char *msg) "Unable to get VSCR from KVM: %s"
+kvm_failed_vr_get(int vr, const char *msg) "Unable to get VR%d from KVM: %s"
+kvm_failed_vpa_addr_get(const char *msg) "Unable to get VPA address from KVM: %s"
+kvm_failed_slb_get(const char *msg) "Unable to get SLB shadow state from KVM: %s"
+kvm_failed_dtl_get(const char *msg) "Unable to get dispatch trace log state from KVM: %s"
+kvm_failed_vpa_addr_set(const char *msg) "Unable to set VPA address to KVM: %s"
+kvm_failed_slb_set(const char *msg) "Unable to set SLB shadow state to KVM: %s"
+kvm_failed_dtl_set(const char *msg) "Unable to set dispatch trace log state to KVM: %s"
+kvm_failed_null_vpa_addr_set(const char *msg) "Unable to set VPA address to KVM: %s"
+kvm_failed_put_vpa(void) "Warning: Unable to set VPA information to KVM"
+kvm_failed_get_vpa(void) "Warning: Unable to get VPA information from KVM"
+kvm_injected_interrupt(int irq) "injected interrupt %d"
+kvm_handle_dcr_write(void) "handle dcr write"
+kvm_handle_drc_read(void) "handle dcr read"
+kvm_handle_halt(void) "handle halt"
+kvm_handle_papr_hcall(void) "handle PAPR hypercall"
+kvm_handle_epr(void) "handle epr"
+kvm_handle_watchdog_expiry(void) "handle watchdog expiry"
+kvm_handle_debug_exception(void) "handle debug exception"
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index dee2bb6910..8d08625c33 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -42,8 +42,8 @@
#define GDBSTUB_SINGLE_STEP 0x4
/* Include definitions for instructions classes and implementations flags */
-//#define PPC_DEBUG_DISAS
-//#define DO_PPC_STATISTICS
+/* #define PPC_DEBUG_DISAS */
+/* #define DO_PPC_STATISTICS */
#ifdef PPC_DEBUG_DISAS
# define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
@@ -54,9 +54,9 @@
/* Code translation helpers */
/* global register indexes */
-static char cpu_reg_names[10*3 + 22*4 /* GPR */
- + 10*4 + 22*5 /* SPE GPRh */
- + 8*5 /* CRF */];
+static char cpu_reg_names[10 * 3 + 22 * 4 /* GPR */
+ + 10 * 4 + 22 * 5 /* SPE GPRh */
+ + 8 * 5 /* CRF */];
static TCGv cpu_gpr[32];
static TCGv cpu_gprh[32];
static TCGv_i32 cpu_crf[8];
@@ -78,7 +78,7 @@ static TCGv_i32 cpu_access_type;
void ppc_translate_init(void)
{
int i;
- char* p;
+ char *p;
size_t cpu_reg_names_size;
p = cpu_reg_names;
@@ -146,7 +146,8 @@ void ppc_translate_init(void)
offsetof(CPUPPCState, fpscr), "fpscr");
cpu_access_type = tcg_global_mem_new_i32(cpu_env,
- offsetof(CPUPPCState, access_type), "access_type");
+ offsetof(CPUPPCState, access_type),
+ "access_type");
}
/* internal defines */
@@ -246,8 +247,9 @@ static void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
{
TCGv_i32 t0, t1;
- /* These are all synchronous exceptions, we set the PC back to
- * the faulting instruction
+ /*
+ * These are all synchronous exceptions, we set the PC back to the
+ * faulting instruction
*/
if (ctx->exception == POWERPC_EXCP_NONE) {
gen_update_nip(ctx, ctx->base.pc_next - 4);
@@ -264,8 +266,9 @@ static void gen_exception(DisasContext *ctx, uint32_t excp)
{
TCGv_i32 t0;
- /* These are all synchronous exceptions, we set the PC back to
- * the faulting instruction
+ /*
+ * These are all synchronous exceptions, we set the PC back to the
+ * faulting instruction
*/
if (ctx->exception == POWERPC_EXCP_NONE) {
gen_update_nip(ctx, ctx->base.pc_next - 4);
@@ -320,8 +323,9 @@ static void gen_debug_exception(DisasContext *ctx)
{
TCGv_i32 t0;
- /* These are all synchronous exceptions, we set the PC back to
- * the faulting instruction
+ /*
+ * These are all synchronous exceptions, we set the PC back to the
+ * faulting instruction
*/
if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
(ctx->exception != POWERPC_EXCP_SYNC)) {
@@ -602,9 +606,11 @@ static inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
tcg_gen_movi_tl(t0, CRF_EQ);
tcg_gen_movi_tl(t1, CRF_LT);
- tcg_gen_movcond_tl((s ? TCG_COND_LT : TCG_COND_LTU), t0, arg0, arg1, t1, t0);
+ tcg_gen_movcond_tl((s ? TCG_COND_LT : TCG_COND_LTU),
+ t0, arg0, arg1, t1, t0);
tcg_gen_movi_tl(t1, CRF_GT);
- tcg_gen_movcond_tl((s ? TCG_COND_GT : TCG_COND_GTU), t0, arg0, arg1, t1, t0);
+ tcg_gen_movcond_tl((s ? TCG_COND_GT : TCG_COND_GTU),
+ t0, arg0, arg1, t1, t0);
tcg_gen_trunc_tl_i32(t, t0);
tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_so);
@@ -840,9 +846,11 @@ static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
if (compute_ca) {
if (NARROW_MODE(ctx)) {
- /* Caution: a non-obvious corner case of the spec is that we
- must produce the *entire* 64-bit addition, but produce the
- carry into bit 32. */
+ /*
+ * Caution: a non-obvious corner case of the spec is that
+ * we must produce the *entire* 64-bit addition, but
+ * produce the carry into bit 32.
+ */
TCGv t1 = tcg_temp_new();
tcg_gen_xor_tl(t1, arg1, arg2); /* add without carry */
tcg_gen_add_tl(t0, arg1, arg2);
@@ -1017,12 +1025,13 @@ static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t3);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, ret);
+ }
}
/* Div functions */
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
-static void glue(gen_, name)(DisasContext *ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)], \
cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
@@ -1091,12 +1100,13 @@ static inline void gen_op_arith_divd(DisasContext *ctx, TCGv ret, TCGv arg1,
tcg_temp_free_i64(t2);
tcg_temp_free_i64(t3);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, ret);
+ }
}
#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
-static void glue(gen_, name)(DisasContext *ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)], \
cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
@@ -1219,8 +1229,9 @@ static void gen_mulhw(DisasContext *ctx)
tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* mulhwu mulhwu. */
@@ -1235,8 +1246,9 @@ static void gen_mulhwu(DisasContext *ctx)
tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* mullw mullw. */
@@ -1255,8 +1267,9 @@ static void gen_mullw(DisasContext *ctx)
tcg_gen_mul_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
cpu_gpr[rB(ctx->opcode)]);
#endif
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* mullwo mullwo. */
@@ -1284,8 +1297,9 @@ static void gen_mullwo(DisasContext *ctx)
tcg_temp_free_i32(t0);
tcg_temp_free_i32(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* mulli */
@@ -1325,8 +1339,9 @@ static void gen_mulld(DisasContext *ctx)
{
tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
cpu_gpr[rB(ctx->opcode)]);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* mulldo mulldo. */
@@ -1369,9 +1384,11 @@ static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
if (compute_ca) {
/* dest = ~arg1 + arg2 [+ ca]. */
if (NARROW_MODE(ctx)) {
- /* Caution: a non-obvious corner case of the spec is that we
- must produce the *entire* 64-bit addition, but produce the
- carry into bit 32. */
+ /*
+ * Caution: a non-obvious corner case of the spec is that
+ * we must produce the *entire* 64-bit addition, but
+ * produce the carry into bit 32.
+ */
TCGv inv1 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
tcg_gen_not_tl(inv1, arg1);
@@ -1404,8 +1421,10 @@ static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
gen_op_arith_compute_ca32(ctx, t0, arg1, arg2, cpu_ca32, 1);
}
} else if (add_ca) {
- /* Since we're ignoring carry-out, we can simplify the
- standard ~arg1 + arg2 + ca to arg2 - arg1 + ca - 1. */
+ /*
+ * Since we're ignoring carry-out, we can simplify the
+ * standard ~arg1 + arg2 + ca to arg2 - arg1 + ca - 1.
+ */
tcg_gen_sub_tl(t0, arg2, arg1);
tcg_gen_add_tl(t0, t0, cpu_ca);
tcg_gen_subi_tl(t0, t0, 1);
@@ -1493,7 +1512,7 @@ static void gen_nego(DisasContext *ctx)
/*** Integer logical ***/
#define GEN_LOGICAL2(name, tcg_op, opc, type) \
-static void glue(gen_, name)(DisasContext *ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], \
cpu_gpr[rB(ctx->opcode)]); \
@@ -1502,7 +1521,7 @@ static void glue(gen_, name)(DisasContext *ctx)
}
#define GEN_LOGICAL1(name, tcg_op, opc, type) \
-static void glue(gen_, name)(DisasContext *ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); \
if (unlikely(Rc(ctx->opcode) != 0)) \
@@ -1517,14 +1536,16 @@ GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
/* andi. */
static void gen_andi_(DisasContext *ctx)
{
- tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
+ tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
+ UIMM(ctx->opcode));
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
/* andis. */
static void gen_andis_(DisasContext *ctx)
{
- tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
+ tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
+ UIMM(ctx->opcode) << 16);
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
}
@@ -1538,8 +1559,9 @@ static void gen_cntlzw(DisasContext *ctx)
tcg_gen_extu_i32_tl(cpu_gpr[rA(ctx->opcode)], t);
tcg_temp_free_i32(t);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* cnttzw */
@@ -1591,12 +1613,14 @@ static void gen_or(DisasContext *ctx)
rb = rB(ctx->opcode);
/* Optimisation for mr. ri case */
if (rs != ra || rs != rb) {
- if (rs != rb)
+ if (rs != rb) {
tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
- else
+ } else {
tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
- if (unlikely(Rc(ctx->opcode) != 0))
+ }
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[ra]);
+ }
} else if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rs]);
#if defined(TARGET_PPC64)
@@ -1654,10 +1678,11 @@ static void gen_or(DisasContext *ctx)
tcg_temp_free(t0);
}
#if !defined(CONFIG_USER_ONLY)
- /* Pause out of TCG otherwise spin loops with smt_low eat too much
- * CPU and the kernel hangs. This applies to all encodings other
- * than no-op, e.g., miso(rs=26), yield(27), mdoio(29), mdoom(30),
- * and all currently undefined.
+ /*
+ * Pause out of TCG otherwise spin loops with smt_low eat too
+ * much CPU and the kernel hangs. This applies to all
+ * encodings other than no-op, e.g., miso(rs=26), yield(27),
+ * mdoio(29), mdoom(30), and all currently undefined.
*/
gen_pause(ctx);
#endif
@@ -1671,12 +1696,15 @@ GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
static void gen_xor(DisasContext *ctx)
{
/* Optimisation for "set to zero" case */
- if (rS(ctx->opcode) != rB(ctx->opcode))
- tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
- else
+ if (rS(ctx->opcode) != rB(ctx->opcode)) {
+ tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
+ cpu_gpr[rB(ctx->opcode)]);
+ } else {
tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
- if (unlikely(Rc(ctx->opcode) != 0))
+ }
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* ori */
@@ -1699,7 +1727,8 @@ static void gen_oris(DisasContext *ctx)
/* NOP */
return;
}
- tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
+ tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
+ uimm << 16);
}
/* xori */
@@ -1723,7 +1752,8 @@ static void gen_xoris(DisasContext *ctx)
/* NOP */
return;
}
- tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
+ tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
+ uimm << 16);
}
/* popcntb : PowerPC 2.03 specification */
@@ -1798,8 +1828,9 @@ GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
static void gen_cntlzd(DisasContext *ctx)
{
tcg_gen_clzi_i64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], 64);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* cnttzd */
@@ -1838,7 +1869,7 @@ static void gen_rlwimi(DisasContext *ctx)
uint32_t mb = MB(ctx->opcode);
uint32_t me = ME(ctx->opcode);
- if (sh == (31-me) && mb <= me) {
+ if (sh == (31 - me) && mb <= me) {
tcg_gen_deposit_tl(t_ra, t_ra, t_rs, sh, me - mb + 1);
} else {
target_ulong mask;
@@ -2141,8 +2172,9 @@ static void gen_slw(DisasContext *ctx)
tcg_temp_free(t1);
tcg_temp_free(t0);
tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* sraw & sraw. */
@@ -2150,8 +2182,9 @@ static void gen_sraw(DisasContext *ctx)
{
gen_helper_sraw(cpu_gpr[rA(ctx->opcode)], cpu_env,
cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* srawi & srawi. */
@@ -2206,8 +2239,9 @@ static void gen_srw(DisasContext *ctx)
tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
tcg_temp_free(t1);
tcg_temp_free(t0);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
#if defined(TARGET_PPC64)
@@ -2226,8 +2260,9 @@ static void gen_sld(DisasContext *ctx)
tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
tcg_temp_free(t1);
tcg_temp_free(t0);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* srad & srad. */
@@ -2235,8 +2270,9 @@ static void gen_srad(DisasContext *ctx)
{
gen_helper_srad(cpu_gpr[rA(ctx->opcode)], cpu_env,
cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* sradi & sradi. */
static inline void gen_sradi(DisasContext *ctx, int n)
@@ -2317,8 +2353,9 @@ static void gen_srd(DisasContext *ctx)
tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
tcg_temp_free(t1);
tcg_temp_free(t0);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
#endif
@@ -2463,7 +2500,7 @@ GEN_QEMU_STORE_64(st64r, BSWAP_MEMOP(MO_Q))
#endif
#define GEN_LD(name, ldop, opc, type) \
-static void glue(gen_, name)(DisasContext *ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv EA; \
gen_set_access_type(ctx, ACCESS_INT); \
@@ -2474,7 +2511,7 @@ static void glue(gen_, name)(DisasContext *ctx)
}
#define GEN_LDU(name, ldop, opc, type) \
-static void glue(gen_, name##u)(DisasContext *ctx) \
+static void glue(gen_, name##u)(DisasContext *ctx) \
{ \
TCGv EA; \
if (unlikely(rA(ctx->opcode) == 0 || \
@@ -2494,7 +2531,7 @@ static void glue(gen_, name##u)(DisasContext *ctx)
}
#define GEN_LDUX(name, ldop, opc2, opc3, type) \
-static void glue(gen_, name##ux)(DisasContext *ctx) \
+static void glue(gen_, name##ux)(DisasContext *ctx) \
{ \
TCGv EA; \
if (unlikely(rA(ctx->opcode) == 0 || \
@@ -2598,8 +2635,9 @@ static void gen_ld(DisasContext *ctx)
/* ld - ldu */
gen_qemu_ld64_i64(ctx, cpu_gpr[rD(ctx->opcode)], EA);
}
- if (Rc(ctx->opcode))
+ if (Rc(ctx->opcode)) {
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
+ }
tcg_temp_free(EA);
}
@@ -2669,7 +2707,7 @@ static void gen_lq(DisasContext *ctx)
/*** Integer store ***/
#define GEN_ST(name, stop, opc, type) \
-static void glue(gen_, name)(DisasContext *ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv EA; \
gen_set_access_type(ctx, ACCESS_INT); \
@@ -2680,7 +2718,7 @@ static void glue(gen_, name)(DisasContext *ctx)
}
#define GEN_STU(name, stop, opc, type) \
-static void glue(gen_, stop##u)(DisasContext *ctx) \
+static void glue(gen_, stop##u)(DisasContext *ctx) \
{ \
TCGv EA; \
if (unlikely(rA(ctx->opcode) == 0)) { \
@@ -2699,7 +2737,7 @@ static void glue(gen_, stop##u)(DisasContext *ctx)
}
#define GEN_STUX(name, stop, opc2, opc3, type) \
-static void glue(gen_, name##ux)(DisasContext *ctx) \
+static void glue(gen_, name##ux)(DisasContext *ctx) \
{ \
TCGv EA; \
if (unlikely(rA(ctx->opcode) == 0)) { \
@@ -2847,8 +2885,9 @@ static void gen_std(DisasContext *ctx)
EA = tcg_temp_new();
gen_addr_imm_index(ctx, EA, 0x03);
gen_qemu_st64_i64(ctx, cpu_gpr[rs], EA);
- if (Rc(ctx->opcode))
+ if (Rc(ctx->opcode)) {
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
+ }
tcg_temp_free(EA);
}
}
@@ -2916,10 +2955,11 @@ static void gen_stmw(DisasContext *ctx)
/*** Integer load and store strings ***/
/* lswi */
-/* PowerPC32 specification says we must generate an exception if
- * rA is in the range of registers to be loaded.
- * In an other hand, IBM says this is valid, but rA won't be loaded.
- * For now, I'll follow the spec...
+/*
+ * PowerPC32 specification says we must generate an exception if rA is
+ * in the range of registers to be loaded. In an other hand, IBM says
+ * this is valid, but rA won't be loaded. For now, I'll follow the
+ * spec...
*/
static void gen_lswi(DisasContext *ctx)
{
@@ -2934,8 +2974,9 @@ static void gen_lswi(DisasContext *ctx)
gen_align_no_le(ctx);
return;
}
- if (nb == 0)
+ if (nb == 0) {
nb = 32;
+ }
nr = DIV_ROUND_UP(nb, 4);
if (unlikely(lsw_reg_in_range(start, nr, ra))) {
gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
@@ -2989,8 +3030,9 @@ static void gen_stswi(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_INT);
t0 = tcg_temp_new();
gen_addr_register(ctx, t0);
- if (nb == 0)
+ if (nb == 0) {
nb = 32;
+ }
t1 = tcg_const_i32(nb);
t2 = tcg_const_i32(rS(ctx->opcode));
gen_helper_stsw(cpu_env, t0, t1, t2);
@@ -3363,8 +3405,10 @@ static void gen_conditional_store(DisasContext *ctx, TCGMemOp memop)
gen_set_label(l1);
- /* Address mismatch implies failure. But we still need to provide the
- memory barrier semantics of the instruction. */
+ /*
+ * Address mismatch implies failure. But we still need to provide
+ * the memory barrier semantics of the instruction.
+ */
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
@@ -3639,8 +3683,9 @@ static void gen_rvwinkle(DisasContext *ctx)
static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
{
#if defined(TARGET_PPC64)
- if (ctx->has_cfar)
+ if (ctx->has_cfar) {
tcg_gen_movi_tl(cpu_cfar, nip);
+ }
#endif
}
@@ -3732,17 +3777,19 @@ static void gen_bcond(DisasContext *ctx, int type)
if (type == BCOND_LR || type == BCOND_CTR || type == BCOND_TAR) {
target = tcg_temp_local_new();
- if (type == BCOND_CTR)
+ if (type == BCOND_CTR) {
tcg_gen_mov_tl(target, cpu_ctr);
- else if (type == BCOND_TAR)
+ } else if (type == BCOND_TAR) {
gen_load_spr(target, SPR_TAR);
- else
+ } else {
tcg_gen_mov_tl(target, cpu_lr);
+ }
} else {
target = NULL;
}
- if (LK(ctx->opcode))
+ if (LK(ctx->opcode)) {
gen_setlr(ctx, ctx->base.pc_next);
+ }
l1 = gen_new_label();
if ((bo & 0x4) == 0) {
/* Decrement and test CTR */
@@ -3857,7 +3904,7 @@ static void gen_bctar(DisasContext *ctx)
/*** Condition register logical ***/
#define GEN_CRLOGIC(name, tcg_op, opc) \
-static void glue(gen_, name)(DisasContext *ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
uint8_t bitmask; \
int sh; \
@@ -3918,7 +3965,8 @@ static void gen_rfi(DisasContext *ctx)
#if defined(CONFIG_USER_ONLY)
GEN_PRIV;
#else
- /* This instruction doesn't exist anymore on 64-bit server
+ /*
+ * This instruction doesn't exist anymore on 64-bit server
* processors compliant with arch 2.x
*/
if (is_book3s_arch2x(ctx)) {
@@ -4157,7 +4205,7 @@ static void gen_mfcr(DisasContext *ctx)
if (likely(ctx->opcode & 0x00100000)) {
crm = CRM(ctx->opcode);
if (likely(crm && ((crm & (crm - 1)) == 0))) {
- crn = ctz32 (crm);
+ crn = ctz32(crm);
tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
cpu_gpr[rD(ctx->opcode)], crn * 4);
@@ -4222,7 +4270,8 @@ static inline void gen_op_mfspr(DisasContext *ctx)
(*read_cb)(ctx, rD(ctx->opcode), sprn);
} else {
/* Privilege exception */
- /* This is a hack to avoid warnings when running Linux:
+ /*
+ * This is a hack to avoid warnings when running Linux:
* this OS breaks the PowerPC virtualisation model,
* allowing userland application to read the PVR
*/
@@ -4245,8 +4294,9 @@ static inline void gen_op_mfspr(DisasContext *ctx)
"Trying to read invalid spr %d (0x%03x) at "
TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
- /* The behaviour depends on MSR:PR and SPR# bit 0x10,
- * it can generate a priv, a hv emu or a no-op
+ /*
+ * The behaviour depends on MSR:PR and SPR# bit 0x10, it can
+ * generate a priv, a hv emu or a no-op
*/
if (sprn & 0x10) {
if (ctx->pr) {
@@ -4280,7 +4330,7 @@ static void gen_mtcrf(DisasContext *ctx)
if (likely((ctx->opcode & 0x00100000))) {
if (crm && ((crm & (crm - 1)) == 0)) {
TCGv_i32 temp = tcg_temp_new_i32();
- crn = ctz32 (crm);
+ crn = ctz32(crm);
tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
tcg_gen_shri_i32(temp, temp, crn * 4);
tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
@@ -4309,14 +4359,17 @@ static void gen_mtmsrd(DisasContext *ctx)
if (ctx->opcode & 0x00010000) {
/* Special form that does not need any synchronisation */
TCGv t0 = tcg_temp_new();
- tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
- tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(target_ulong)((1 << MSR_RI) | (1 << MSR_EE)));
+ tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)],
+ (1 << MSR_RI) | (1 << MSR_EE));
+ tcg_gen_andi_tl(cpu_msr, cpu_msr,
+ ~(target_ulong)((1 << MSR_RI) | (1 << MSR_EE)));
tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
tcg_temp_free(t0);
} else {
- /* XXX: we need to update nip before the store
- * if we enter power saving mode, we will exit the loop
- * directly from ppc_store_msr
+ /*
+ * XXX: we need to update nip before the store if we enter
+ * power saving mode, we will exit the loop directly from
+ * ppc_store_msr
*/
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
@@ -4342,16 +4395,19 @@ static void gen_mtmsr(DisasContext *ctx)
if (ctx->opcode & 0x00010000) {
/* Special form that does not need any synchronisation */
TCGv t0 = tcg_temp_new();
- tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
- tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(target_ulong)((1 << MSR_RI) | (1 << MSR_EE)));
+ tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)],
+ (1 << MSR_RI) | (1 << MSR_EE));
+ tcg_gen_andi_tl(cpu_msr, cpu_msr,
+ ~(target_ulong)((1 << MSR_RI) | (1 << MSR_EE)));
tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
tcg_temp_free(t0);
} else {
TCGv msr = tcg_temp_new();
- /* XXX: we need to update nip before the store
- * if we enter power saving mode, we will exit the loop
- * directly from ppc_store_msr
+ /*
+ * XXX: we need to update nip before the store if we enter
+ * power saving mode, we will exit the loop directly from
+ * ppc_store_msr
*/
if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
gen_io_start();
@@ -4415,8 +4471,9 @@ static void gen_mtspr(DisasContext *ctx)
TARGET_FMT_lx "\n", sprn, sprn, ctx->base.pc_next - 4);
- /* The behaviour depends on MSR:PR and SPR# bit 0x10,
- * it can generate a priv, a hv emu or a no-op
+ /*
+ * The behaviour depends on MSR:PR and SPR# bit 0x10, it can
+ * generate a priv, a hv emu or a no-op
*/
if (sprn & 0x10) {
if (ctx->pr) {
@@ -4526,36 +4583,40 @@ static void gen_dcbstep(DisasContext *ctx)
/* dcbt */
static void gen_dcbt(DisasContext *ctx)
{
- /* interpreted as no-op */
- /* XXX: specification say this is treated as a load by the MMU
- * but does not generate any exception
+ /*
+ * interpreted as no-op
+ * XXX: specification say this is treated as a load by the MMU but
+ * does not generate any exception
*/
}
/* dcbtep */
static void gen_dcbtep(DisasContext *ctx)
{
- /* interpreted as no-op */
- /* XXX: specification say this is treated as a load by the MMU
- * but does not generate any exception
+ /*
+ * interpreted as no-op
+ * XXX: specification say this is treated as a load by the MMU but
+ * does not generate any exception
*/
}
/* dcbtst */
static void gen_dcbtst(DisasContext *ctx)
{
- /* interpreted as no-op */
- /* XXX: specification say this is treated as a load by the MMU
- * but does not generate any exception
+ /*
+ * interpreted as no-op
+ * XXX: specification say this is treated as a load by the MMU but
+ * does not generate any exception
*/
}
/* dcbtstep */
static void gen_dcbtstep(DisasContext *ctx)
{
- /* interpreted as no-op */
- /* XXX: specification say this is treated as a load by the MMU
- * but does not generate any exception
+ /*
+ * interpreted as no-op
+ * XXX: specification say this is treated as a load by the MMU but
+ * does not generate any exception
*/
}
@@ -4653,8 +4714,9 @@ static void gen_icbiep(DisasContext *ctx)
/* dcba */
static void gen_dcba(DisasContext *ctx)
{
- /* interpreted as no-op */
- /* XXX: specification say this is treated as a store by the MMU
+ /*
+ * interpreted as no-op
+ * XXX: specification say this is treated as a store by the MMU
* but does not generate any exception
*/
}
@@ -5021,8 +5083,9 @@ static void gen_abs(DisasContext *ctx)
gen_set_label(l1);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
gen_set_label(l2);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* abso - abso. */
@@ -5044,8 +5107,9 @@ static void gen_abso(DisasContext *ctx)
gen_set_label(l2);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
gen_set_label(l3);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* clcs */
@@ -5062,8 +5126,9 @@ static void gen_div(DisasContext *ctx)
{
gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
cpu_gpr[rB(ctx->opcode)]);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* divo - divo. */
@@ -5071,8 +5136,9 @@ static void gen_divo(DisasContext *ctx)
{
gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
cpu_gpr[rB(ctx->opcode)]);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* divs - divs. */
@@ -5080,8 +5146,9 @@ static void gen_divs(DisasContext *ctx)
{
gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_env, cpu_gpr[rA(ctx->opcode)],
cpu_gpr[rB(ctx->opcode)]);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* divso - divso. */
@@ -5089,8 +5156,9 @@ static void gen_divso(DisasContext *ctx)
{
gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_env,
cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* doz - doz. */
@@ -5098,14 +5166,17 @@ static void gen_doz(DisasContext *ctx)
{
TCGLabel *l1 = gen_new_label();
TCGLabel *l2 = gen_new_label();
- tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
- tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
+ tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)],
+ cpu_gpr[rA(ctx->opcode)], l1);
+ tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
+ cpu_gpr[rA(ctx->opcode)]);
tcg_gen_br(l2);
gen_set_label(l1);
tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
gen_set_label(l2);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* dozo - dozo. */
@@ -5118,7 +5189,8 @@ static void gen_dozo(DisasContext *ctx)
TCGv t2 = tcg_temp_new();
/* Start with XER OV disabled, the most likely case */
tcg_gen_movi_tl(cpu_ov, 0);
- tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
+ tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)],
+ cpu_gpr[rA(ctx->opcode)], l1);
tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
@@ -5134,8 +5206,9 @@ static void gen_dozo(DisasContext *ctx)
tcg_temp_free(t0);
tcg_temp_free(t1);
tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* dozi */
@@ -5150,8 +5223,9 @@ static void gen_dozi(DisasContext *ctx)
gen_set_label(l1);
tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
gen_set_label(l2);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* lscbx - lscbx. */
@@ -5169,8 +5243,9 @@ static void gen_lscbx(DisasContext *ctx)
tcg_temp_free_i32(t3);
tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, t0);
+ }
tcg_temp_free(t0);
}
@@ -5196,8 +5271,9 @@ static void gen_maskg(DisasContext *ctx)
tcg_temp_free(t1);
tcg_temp_free(t2);
tcg_temp_free(t3);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* maskir - maskir. */
@@ -5210,8 +5286,9 @@ static void gen_maskir(DisasContext *ctx)
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* mul - mul. */
@@ -5230,8 +5307,9 @@ static void gen_mul(DisasContext *ctx)
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* mulo - mulo. */
@@ -5258,8 +5336,9 @@ static void gen_mulo(DisasContext *ctx)
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* nabs - nabs. */
@@ -5273,8 +5352,9 @@ static void gen_nabs(DisasContext *ctx)
gen_set_label(l1);
tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
gen_set_label(l2);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* nabso - nabso. */
@@ -5290,8 +5370,9 @@ static void gen_nabso(DisasContext *ctx)
gen_set_label(l2);
/* nabs never overflows */
tcg_gen_movi_tl(cpu_ov, 0);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
+ }
}
/* rlmi - rlmi. */
@@ -5303,11 +5384,13 @@ static void gen_rlmi(DisasContext *ctx)
tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
tcg_gen_andi_tl(t0, t0, MASK(mb, me));
- tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
+ tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
+ ~MASK(mb, me));
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
tcg_temp_free(t0);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* rrib - rrib. */
@@ -5324,8 +5407,9 @@ static void gen_rrib(DisasContext *ctx)
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* sle - sle. */
@@ -5342,8 +5426,9 @@ static void gen_sle(DisasContext *ctx)
gen_store_spr(SPR_MQ, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* sleq - sleq. */
@@ -5364,8 +5449,9 @@ static void gen_sleq(DisasContext *ctx)
tcg_temp_free(t0);
tcg_temp_free(t1);
tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* sliq - sliq. */
@@ -5381,8 +5467,9 @@ static void gen_sliq(DisasContext *ctx)
gen_store_spr(SPR_MQ, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* slliq - slliq. */
@@ -5399,8 +5486,9 @@ static void gen_slliq(DisasContext *ctx)
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* sllq - sllq. */
@@ -5428,8 +5516,9 @@ static void gen_sllq(DisasContext *ctx)
tcg_temp_free(t0);
tcg_temp_free(t1);
tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* slq - slq. */
@@ -5451,8 +5540,9 @@ static void gen_slq(DisasContext *ctx)
gen_set_label(l1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* sraiq - sraiq. */
@@ -5474,8 +5564,9 @@ static void gen_sraiq(DisasContext *ctx)
tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
tcg_temp_free(t0);
tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* sraq - sraq. */
@@ -5507,8 +5598,9 @@ static void gen_sraq(DisasContext *ctx)
gen_set_label(l2);
tcg_temp_free(t1);
tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* sre - sre. */
@@ -5525,8 +5617,9 @@ static void gen_sre(DisasContext *ctx)
gen_store_spr(SPR_MQ, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* srea - srea. */
@@ -5540,8 +5633,9 @@ static void gen_srea(DisasContext *ctx)
tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* sreq */
@@ -5562,8 +5656,9 @@ static void gen_sreq(DisasContext *ctx)
tcg_temp_free(t0);
tcg_temp_free(t1);
tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* sriq */
@@ -5579,8 +5674,9 @@ static void gen_sriq(DisasContext *ctx)
gen_store_spr(SPR_MQ, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* srliq */
@@ -5597,8 +5693,9 @@ static void gen_srliq(DisasContext *ctx)
tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* srlq */
@@ -5627,8 +5724,9 @@ static void gen_srlq(DisasContext *ctx)
tcg_temp_free(t0);
tcg_temp_free(t1);
tcg_temp_free(t2);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* srq */
@@ -5650,8 +5748,9 @@ static void gen_srq(DisasContext *ctx)
gen_set_label(l1);
tcg_temp_free(t0);
tcg_temp_free(t1);
- if (unlikely(Rc(ctx->opcode) != 0))
+ if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
+ }
}
/* PowerPC 602 specific instructions */
@@ -5769,8 +5868,9 @@ static void gen_mfsri(DisasContext *ctx)
tcg_gen_extract_tl(t0, t0, 28, 4);
gen_helper_load_sr(cpu_gpr[rd], cpu_env, t0);
tcg_temp_free(t0);
- if (ra != 0 && ra != rd)
+ if (ra != 0 && ra != rd) {
tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
+ }
#endif /* defined(CONFIG_USER_ONLY) */
}
@@ -6147,9 +6247,10 @@ static void gen_dcread(DisasContext *ctx)
/* icbt */
static void gen_icbt_40x(DisasContext *ctx)
{
- /* interpreted as no-op */
- /* XXX: specification say this is treated as a load by the MMU
- * but does not generate any exception
+ /*
+ * interpreted as no-op
+ * XXX: specification say this is treated as a load by the MMU but
+ * does not generate any exception
*/
}
@@ -6440,7 +6541,7 @@ static void gen_tlbilx_booke206(DisasContext *ctx)
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
- switch((ctx->opcode >> 21) & 0x3) {
+ switch ((ctx->opcode >> 21) & 0x3) {
case 0:
gen_helper_booke206_tlbilx0(cpu_env, t0);
break;
@@ -6474,8 +6575,9 @@ static void gen_wrtee(DisasContext *ctx)
tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
tcg_temp_free(t0);
- /* Stop translation to have a chance to raise an exception
- * if we just set msr_ee to 1
+ /*
+ * Stop translation to have a chance to raise an exception if we
+ * just set msr_ee to 1
*/
gen_stop_exception(ctx);
#endif /* defined(CONFIG_USER_ONLY) */
@@ -6529,9 +6631,10 @@ static void gen_msync_4xx(DisasContext *ctx)
/* icbt */
static void gen_icbt_440(DisasContext *ctx)
{
- /* interpreted as no-op */
- /* XXX: specification say this is treated as a load by the MMU
- * but does not generate any exception
+ /*
+ * interpreted as no-op
+ * XXX: specification say this is treated as a load by the MMU but
+ * does not generate any exception
*/
}
@@ -6625,7 +6728,8 @@ static inline void gen_##name(DisasContext *ctx) \
gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); \
return; \
} \
- /* Because tbegin always fails in QEMU, these user \
+ /* \
+ * Because tbegin always fails in QEMU, these user \
* space instructions all have a simple implementation: \
* \
* CR[0] = 0b0 || MSR[TS] || 0b0 \
@@ -6641,17 +6745,18 @@ GEN_TM_NOOP(tabortwci);
GEN_TM_NOOP(tabortdc);
GEN_TM_NOOP(tabortdci);
GEN_TM_NOOP(tsr);
+
static inline void gen_cp_abort(DisasContext *ctx)
{
- // Do Nothing
+ /* Do Nothing */
}
#define GEN_CP_PASTE_NOOP(name) \
static inline void gen_##name(DisasContext *ctx) \
{ \
- /* Generate invalid exception until \
- * we have an implementation of the copy \
- * paste facility \
+ /* \
+ * Generate invalid exception until we have an \
+ * implementation of the copy paste facility \
*/ \
gen_invalid(ctx); \
}
@@ -6665,8 +6770,9 @@ static void gen_tcheck(DisasContext *ctx)
gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM);
return;
}
- /* Because tbegin always fails, the tcheck implementation
- * is simple:
+ /*
+ * Because tbegin always fails, the tcheck implementation is
+ * simple:
*
* CR[CRF] = TDOOMED || MSR[TS] || 0b0
* = 0b1 || 0b00 || 0b0
@@ -6678,7 +6784,7 @@ static void gen_tcheck(DisasContext *ctx)
#define GEN_TM_PRIV_NOOP(name) \
static inline void gen_##name(DisasContext *ctx) \
{ \
- gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); \
+ gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC); \
}
#else
@@ -6691,7 +6797,8 @@ static inline void gen_##name(DisasContext *ctx) \
gen_exception_err(ctx, POWERPC_EXCP_FU, FSCR_IC_TM); \
return; \
} \
- /* Because tbegin always fails, the implementation is \
+ /* \
+ * Because tbegin always fails, the implementation is \
* simple: \
* \
* CR[0] = 0b0 || MSR[TS] || 0b0 \
@@ -6973,8 +7080,10 @@ GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B),
GEN_HANDLER2(slbfee_, "slbfee.", 0x1F, 0x13, 0x1E, 0x001F0000, PPC_SEGMENT_64B),
#endif
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
-/* XXX Those instructions will need to be handled differently for
- * different ISA versions */
+/*
+ * XXX Those instructions will need to be handled differently for
+ * different ISA versions
+ */
GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x001F0001, PPC_MEM_TLBIE),
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x001F0001, PPC_MEM_TLBIE),
GEN_HANDLER_E(tlbiel, 0x1F, 0x12, 0x08, 0x00100001, PPC_NONE, PPC2_ISA300),
@@ -7444,11 +7553,13 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
);
#endif
for (i = 0; i < 32; i++) {
- if ((i & (RGPL - 1)) == 0)
+ if ((i & (RGPL - 1)) == 0) {
qemu_fprintf(f, "GPR%02d", i);
+ }
qemu_fprintf(f, " %016" PRIx64, ppc_dump_gpr(env, i));
- if ((i & (RGPL - 1)) == (RGPL - 1))
+ if ((i & (RGPL - 1)) == (RGPL - 1)) {
qemu_fprintf(f, "\n");
+ }
}
qemu_fprintf(f, "CR ");
for (i = 0; i < 8; i++)
@@ -7456,12 +7567,13 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
qemu_fprintf(f, " [");
for (i = 0; i < 8; i++) {
char a = '-';
- if (env->crf[i] & 0x08)
+ if (env->crf[i] & 0x08) {
a = 'L';
- else if (env->crf[i] & 0x04)
+ } else if (env->crf[i] & 0x04) {
a = 'G';
- else if (env->crf[i] & 0x02)
+ } else if (env->crf[i] & 0x02) {
a = 'E';
+ }
qemu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
}
qemu_fprintf(f, " ] RES " TARGET_FMT_lx "\n",
@@ -7543,8 +7655,9 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
}
#endif
- if (env->spr_cb[SPR_LPCR].name)
+ if (env->spr_cb[SPR_LPCR].name) {
qemu_fprintf(f, " LPCR " TARGET_FMT_lx "\n", env->spr[SPR_LPCR]);
+ }
switch (env->mmu_model) {
case POWERPC_MMU_32B:
@@ -7610,8 +7723,9 @@ void ppc_cpu_dump_statistics(CPUState *cs, int flags)
t3 = ind_table(handler);
for (op3 = 0; op3 < 32; op3++) {
handler = t3[op3];
- if (handler->count == 0)
+ if (handler->count == 0) {
continue;
+ }
qemu_printf("%02x %02x %02x (%02x %04d) %16s: "
"%016" PRIx64 " %" PRId64 "\n",
op1, op2, op3, op1, (op3 << 5) | op2,
@@ -7619,8 +7733,9 @@ void ppc_cpu_dump_statistics(CPUState *cs, int flags)
handler->count, handler->count);
}
} else {
- if (handler->count == 0)
+ if (handler->count == 0) {
continue;
+ }
qemu_printf("%02x %02x (%02x %04d) %16s: "
"%016" PRIx64 " %" PRId64 "\n",
op1, op2, op1, op2, handler->oname,
@@ -7628,8 +7743,9 @@ void ppc_cpu_dump_statistics(CPUState *cs, int flags)
}
}
} else {
- if (handler->count == 0)
+ if (handler->count == 0) {
continue;
+ }
qemu_printf("%02x (%02x ) %16s: %016" PRIx64
" %" PRId64 "\n",
op1, op1, handler->oname,
@@ -7669,14 +7785,16 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|| (env->mmu_model & POWERPC_MMU_64B);
ctx->fpu_enabled = !!msr_fp;
- if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
+ if ((env->flags & POWERPC_FLAG_SPE) && msr_spe) {
ctx->spe_enabled = !!msr_spe;
- else
+ } else {
ctx->spe_enabled = false;
- if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
+ }
+ if ((env->flags & POWERPC_FLAG_VRE) && msr_vr) {
ctx->altivec_enabled = !!msr_vr;
- else
+ } else {
ctx->altivec_enabled = false;
+ }
if ((env->flags & POWERPC_FLAG_VSX) && msr_vsx) {
ctx->vsx_enabled = !!msr_vsx;
} else {
@@ -7690,12 +7808,14 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
}
#endif
ctx->gtse = !!(env->spr[SPR_LPCR] & LPCR_GTSE);
- if ((env->flags & POWERPC_FLAG_SE) && msr_se)
+ if ((env->flags & POWERPC_FLAG_SE) && msr_se) {
ctx->singlestep_enabled = CPU_SINGLE_STEP;
- else
+ } else {
ctx->singlestep_enabled = 0;
- if ((env->flags & POWERPC_FLAG_BE) && msr_be)
+ }
+ if ((env->flags & POWERPC_FLAG_BE) && msr_be) {
ctx->singlestep_enabled |= CPU_BRANCH_STEP;
+ }
if ((env->flags & POWERPC_FLAG_DE) && msr_de) {
ctx->singlestep_enabled = 0;
target_ulong dbcr0 = env->spr[SPR_BOOKE_DBCR0];
@@ -7710,7 +7830,7 @@ static void ppc_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
if (unlikely(ctx->base.singlestep_enabled)) {
ctx->singlestep_enabled |= GDBSTUB_SINGLE_STEP;
}
-#if defined (DO_SINGLE_STEP) && 0
+#if defined(DO_SINGLE_STEP) && 0
/* Single step trace mode */
msr_se = 1;
#endif
@@ -7735,10 +7855,12 @@ static bool ppc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
gen_debug_exception(ctx);
dcbase->is_jmp = DISAS_NORETURN;
- /* The address covered by the breakpoint must be included in
- [tb->pc, tb->pc + tb->size) in order to for it to be
- properly cleared -- thus we increment the PC here so that
- the logic setting tb->size below does the right thing. */
+ /*
+ * The address covered by the breakpoint must be included in
+ * [tb->pc, tb->pc + tb->size) in order to for it to be properly
+ * cleared -- thus we increment the PC here so that the logic
+ * setting tb->size below does the right thing.
+ */
ctx->base.pc_next += 4;
return true;
}
diff --git a/target/ppc/translate/fp-impl.inc.c b/target/ppc/translate/fp-impl.inc.c
index 0f21a4e477..9dcff947c0 100644
--- a/target/ppc/translate/fp-impl.inc.c
+++ b/target/ppc/translate/fp-impl.inc.c
@@ -585,11 +585,13 @@ static void gen_mcrfs(DisasContext *ctx)
shift = 4 * nibble;
tcg_gen_shri_tl(tmp, cpu_fpscr, shift);
tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
- tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
+ tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],
+ 0xf);
tcg_temp_free(tmp);
tcg_gen_extu_tl_i64(tnew_fpscr, cpu_fpscr);
/* Only the exception bits (including FX) should be cleared if read */
- tcg_gen_andi_i64(tnew_fpscr, tnew_fpscr, ~((0xF << shift) & FP_EX_CLEAR_BITS));
+ tcg_gen_andi_i64(tnew_fpscr, tnew_fpscr,
+ ~((0xF << shift) & FP_EX_CLEAR_BITS));
/* FEX and VX need to be updated, so don't set fpscr directly */
tmask = tcg_const_i32(1 << nibble);
gen_helper_store_fpscr(cpu_env, tnew_fpscr, tmask);
@@ -735,7 +737,7 @@ static void gen_mtfsfi(DisasContext *ctx)
/*** Floating-point load ***/
#define GEN_LDF(name, ldop, opc, type) \
-static void glue(gen_, name)(DisasContext *ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv EA; \
TCGv_i64 t0; \
@@ -754,7 +756,7 @@ static void glue(gen_, name)(DisasContext *ctx)
}
#define GEN_LDUF(name, ldop, opc, type) \
-static void glue(gen_, name##u)(DisasContext *ctx) \
+static void glue(gen_, name##u)(DisasContext *ctx) \
{ \
TCGv EA; \
TCGv_i64 t0; \
@@ -778,7 +780,7 @@ static void glue(gen_, name##u)(DisasContext *ctx)
}
#define GEN_LDUXF(name, ldop, opc, type) \
-static void glue(gen_, name##ux)(DisasContext *ctx) \
+static void glue(gen_, name##ux)(DisasContext *ctx) \
{ \
TCGv EA; \
TCGv_i64 t0; \
@@ -802,7 +804,7 @@ static void glue(gen_, name##ux)(DisasContext *ctx)
}
#define GEN_LDXF(name, ldop, opc2, opc3, type) \
-static void glue(gen_, name##x)(DisasContext *ctx) \
+static void glue(gen_, name##x)(DisasContext *ctx) \
{ \
TCGv EA; \
TCGv_i64 t0; \
@@ -872,8 +874,10 @@ static void gen_lfdp(DisasContext *ctx)
EA = tcg_temp_new();
gen_addr_imm_index(ctx, EA, 0);
t0 = tcg_temp_new_i64();
- /* We only need to swap high and low halves. gen_qemu_ld64_i64 does
- necessary 64-bit byteswap already. */
+ /*
+ * We only need to swap high and low halves. gen_qemu_ld64_i64
+ * does necessary 64-bit byteswap already.
+ */
if (unlikely(ctx->le_mode)) {
gen_qemu_ld64_i64(ctx, t0, EA);
set_fpr(rD(ctx->opcode) + 1, t0);
@@ -904,8 +908,10 @@ static void gen_lfdpx(DisasContext *ctx)
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
t0 = tcg_temp_new_i64();
- /* We only need to swap high and low halves. gen_qemu_ld64_i64 does
- necessary 64-bit byteswap already. */
+ /*
+ * We only need to swap high and low halves. gen_qemu_ld64_i64
+ * does necessary 64-bit byteswap already.
+ */
if (unlikely(ctx->le_mode)) {
gen_qemu_ld64_i64(ctx, t0, EA);
set_fpr(rD(ctx->opcode) + 1, t0);
@@ -966,7 +972,7 @@ static void gen_lfiwzx(DisasContext *ctx)
}
/*** Floating-point store ***/
#define GEN_STF(name, stop, opc, type) \
-static void glue(gen_, name)(DisasContext *ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv EA; \
TCGv_i64 t0; \
@@ -985,7 +991,7 @@ static void glue(gen_, name)(DisasContext *ctx)
}
#define GEN_STUF(name, stop, opc, type) \
-static void glue(gen_, name##u)(DisasContext *ctx) \
+static void glue(gen_, name##u)(DisasContext *ctx) \
{ \
TCGv EA; \
TCGv_i64 t0; \
@@ -1009,7 +1015,7 @@ static void glue(gen_, name##u)(DisasContext *ctx)
}
#define GEN_STUXF(name, stop, opc, type) \
-static void glue(gen_, name##ux)(DisasContext *ctx) \
+static void glue(gen_, name##ux)(DisasContext *ctx) \
{ \
TCGv EA; \
TCGv_i64 t0; \
@@ -1033,7 +1039,7 @@ static void glue(gen_, name##ux)(DisasContext *ctx)
}
#define GEN_STXF(name, stop, opc2, opc3, type) \
-static void glue(gen_, name##x)(DisasContext *ctx) \
+static void glue(gen_, name##x)(DisasContext *ctx) \
{ \
TCGv EA; \
TCGv_i64 t0; \
@@ -1103,8 +1109,10 @@ static void gen_stfdp(DisasContext *ctx)
EA = tcg_temp_new();
t0 = tcg_temp_new_i64();
gen_addr_imm_index(ctx, EA, 0);
- /* We only need to swap high and low halves. gen_qemu_st64_i64 does
- necessary 64-bit byteswap already. */
+ /*
+ * We only need to swap high and low halves. gen_qemu_st64_i64
+ * does necessary 64-bit byteswap already.
+ */
if (unlikely(ctx->le_mode)) {
get_fpr(t0, rD(ctx->opcode) + 1);
gen_qemu_st64_i64(ctx, t0, EA);
@@ -1135,8 +1143,10 @@ static void gen_stfdpx(DisasContext *ctx)
EA = tcg_temp_new();
t0 = tcg_temp_new_i64();
gen_addr_reg_index(ctx, EA);
- /* We only need to swap high and low halves. gen_qemu_st64_i64 does
- necessary 64-bit byteswap already. */
+ /*
+ * We only need to swap high and low halves. gen_qemu_st64_i64
+ * does necessary 64-bit byteswap already.
+ */
if (unlikely(ctx->le_mode)) {
get_fpr(t0, rD(ctx->opcode) + 1);
gen_qemu_st64_i64(ctx, t0, EA);
@@ -1204,8 +1214,9 @@ static void gen_lfqu(DisasContext *ctx)
gen_addr_add(ctx, t1, t0, 8);
gen_qemu_ld64_i64(ctx, t2, t1);
set_fpr((rd + 1) % 32, t2);
- if (ra != 0)
+ if (ra != 0) {
tcg_gen_mov_tl(cpu_gpr[ra], t0);
+ }
tcg_temp_free(t0);
tcg_temp_free(t1);
tcg_temp_free_i64(t2);
@@ -1229,8 +1240,9 @@ static void gen_lfqux(DisasContext *ctx)
gen_qemu_ld64_i64(ctx, t2, t1);
set_fpr((rd + 1) % 32, t2);
tcg_temp_free(t1);
- if (ra != 0)
+ if (ra != 0) {
tcg_gen_mov_tl(cpu_gpr[ra], t0);
+ }
tcg_temp_free(t0);
tcg_temp_free_i64(t2);
}
diff --git a/target/ppc/translate/spe-impl.inc.c b/target/ppc/translate/spe-impl.inc.c
index 8c1c16c63e..7ab0a29b5f 100644
--- a/target/ppc/translate/spe-impl.inc.c
+++ b/target/ppc/translate/spe-impl.inc.c
@@ -18,7 +18,8 @@ static inline void gen_evmra(DisasContext *ctx)
TCGv_i64 tmp = tcg_temp_new_i64();
/* tmp := rA_lo + rA_hi << 32 */
- tcg_gen_concat_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
+ tcg_gen_concat_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)],
+ cpu_gprh[rA(ctx->opcode)]);
/* spe_acc := tmp */
tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
@@ -780,7 +781,7 @@ static inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
}
#define GEN_SPEOP_LDST(name, opc2, sh) \
-static void glue(gen_, name)(DisasContext *ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv t0; \
if (unlikely(!ctx->spe_enabled)) { \
@@ -1089,7 +1090,8 @@ static inline void gen_efsabs(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_SPEU);
return;
}
- tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
+ tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
+ (target_long)~0x80000000LL);
}
static inline void gen_efsnabs(DisasContext *ctx)
{
@@ -1097,7 +1099,8 @@ static inline void gen_efsnabs(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_SPEU);
return;
}
- tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
+ tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
+ 0x80000000);
}
static inline void gen_efsneg(DisasContext *ctx)
{
@@ -1105,7 +1108,8 @@ static inline void gen_efsneg(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_SPEU);
return;
}
- tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
+ tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
+ 0x80000000);
}
/* Conversion */
diff --git a/target/ppc/translate/vmx-impl.inc.c b/target/ppc/translate/vmx-impl.inc.c
index eb10c533ca..bd3ff40e68 100644
--- a/target/ppc/translate/vmx-impl.inc.c
+++ b/target/ppc/translate/vmx-impl.inc.c
@@ -15,7 +15,7 @@ static inline TCGv_ptr gen_avr_ptr(int reg)
}
#define GEN_VR_LDX(name, opc2, opc3) \
-static void glue(gen_, name)(DisasContext *ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv EA; \
TCGv_i64 avr; \
@@ -28,8 +28,10 @@ static void glue(gen_, name)(DisasContext *ctx)
EA = tcg_temp_new(); \
gen_addr_reg_index(ctx, EA); \
tcg_gen_andi_tl(EA, EA, ~0xf); \
- /* We only need to swap high and low halves. gen_qemu_ld64_i64 does \
- necessary 64-bit byteswap already. */ \
+ /* \
+ * We only need to swap high and low halves. gen_qemu_ld64_i64 \
+ * does necessary 64-bit byteswap already. \
+ */ \
if (ctx->le_mode) { \
gen_qemu_ld64_i64(ctx, avr, EA); \
set_avr64(rD(ctx->opcode), avr, false); \
@@ -61,8 +63,10 @@ static void gen_st##name(DisasContext *ctx) \
EA = tcg_temp_new(); \
gen_addr_reg_index(ctx, EA); \
tcg_gen_andi_tl(EA, EA, ~0xf); \
- /* We only need to swap high and low halves. gen_qemu_st64_i64 does \
- necessary 64-bit byteswap already. */ \
+ /* \
+ * We only need to swap high and low halves. gen_qemu_st64_i64 \
+ * does necessary 64-bit byteswap already. \
+ */ \
if (ctx->le_mode) { \
get_avr64(avr, rD(ctx->opcode), false); \
gen_qemu_st64_i64(ctx, avr, EA); \
@@ -296,7 +300,7 @@ GEN_VXFORM_V(vnand, MO_64, tcg_gen_gvec_nand, 2, 22);
GEN_VXFORM_V(vorc, MO_64, tcg_gen_gvec_orc, 2, 21);
#define GEN_VXFORM(name, opc2, opc3) \
-static void glue(gen_, name)(DisasContext *ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv_ptr ra, rb, rd; \
if (unlikely(!ctx->altivec_enabled)) { \
@@ -306,7 +310,7 @@ static void glue(gen_, name)(DisasContext *ctx)
ra = gen_avr_ptr(rA(ctx->opcode)); \
rb = gen_avr_ptr(rB(ctx->opcode)); \
rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name (rd, ra, rb); \
+ gen_helper_##name(rd, ra, rb); \
tcg_temp_free_ptr(ra); \
tcg_temp_free_ptr(rb); \
tcg_temp_free_ptr(rd); \
@@ -758,7 +762,7 @@ GEN_VXFORM_DUPI(vspltish, tcg_gen_gvec_dup16i, 6, 13);
GEN_VXFORM_DUPI(vspltisw, tcg_gen_gvec_dup32i, 6, 14);
#define GEN_VXFORM_NOA(name, opc2, opc3) \
-static void glue(gen_, name)(DisasContext *ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv_ptr rb, rd; \
if (unlikely(!ctx->altivec_enabled)) { \
@@ -767,9 +771,9 @@ static void glue(gen_, name)(DisasContext *ctx)
} \
rb = gen_avr_ptr(rB(ctx->opcode)); \
rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name (rd, rb); \
+ gen_helper_##name(rd, rb); \
tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(rd); \
+ tcg_temp_free_ptr(rd); \
}
#define GEN_VXFORM_NOA_ENV(name, opc2, opc3) \
@@ -943,7 +947,7 @@ static void gen_vsldoi(DisasContext *ctx)
rb = gen_avr_ptr(rB(ctx->opcode));
rd = gen_avr_ptr(rD(ctx->opcode));
sh = tcg_const_i32(VSH(ctx->opcode));
- gen_helper_vsldoi (rd, ra, rb, sh);
+ gen_helper_vsldoi(rd, ra, rb, sh);
tcg_temp_free_ptr(ra);
tcg_temp_free_ptr(rb);
tcg_temp_free_ptr(rd);
diff --git a/target/ppc/translate/vsx-impl.inc.c b/target/ppc/translate/vsx-impl.inc.c
index 489b2436e4..11d9b75d01 100644
--- a/target/ppc/translate/vsx-impl.inc.c
+++ b/target/ppc/translate/vsx-impl.inc.c
@@ -751,7 +751,7 @@ static void gen_xxpermdi(DisasContext *ctx)
#define SGN_MASK_SP 0x8000000080000000ull
#define VSX_SCALAR_MOVE(name, op, sgn_mask) \
-static void glue(gen_, name)(DisasContext * ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv_i64 xb, sgm; \
if (unlikely(!ctx->vsx_enabled)) { \
@@ -848,7 +848,7 @@ VSX_SCALAR_MOVE_QP(xsnegqp, OP_NEG, SGN_MASK_DP)
VSX_SCALAR_MOVE_QP(xscpsgnqp, OP_CPSGN, SGN_MASK_DP)
#define VSX_VECTOR_MOVE(name, op, sgn_mask) \
-static void glue(gen_, name)(DisasContext * ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv_i64 xbh, xbl, sgm; \
if (unlikely(!ctx->vsx_enabled)) { \
@@ -910,7 +910,7 @@ VSX_VECTOR_MOVE(xvnegsp, OP_NEG, SGN_MASK_SP)
VSX_VECTOR_MOVE(xvcpsgnsp, OP_CPSGN, SGN_MASK_SP)
#define GEN_VSX_HELPER_2(name, op1, op2, inval, type) \
-static void gen_##name(DisasContext * ctx) \
+static void gen_##name(DisasContext *ctx) \
{ \
TCGv_i32 opc; \
if (unlikely(!ctx->vsx_enabled)) { \
@@ -923,7 +923,7 @@ static void gen_##name(DisasContext * ctx) \
}
#define GEN_VSX_HELPER_XT_XB_ENV(name, op1, op2, inval, type) \
-static void gen_##name(DisasContext * ctx) \
+static void gen_##name(DisasContext *ctx) \
{ \
TCGv_i64 t0; \
TCGv_i64 t1; \
@@ -1230,7 +1230,7 @@ static void gen_xxbrw(DisasContext *ctx)
}
#define VSX_LOGICAL(name, vece, tcg_op) \
-static void glue(gen_, name)(DisasContext * ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
if (unlikely(!ctx->vsx_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
@@ -1251,7 +1251,7 @@ VSX_LOGICAL(xxlnand, MO_64, tcg_gen_gvec_nand)
VSX_LOGICAL(xxlorc, MO_64, tcg_gen_gvec_orc)
#define VSX_XXMRG(name, high) \
-static void glue(gen_, name)(DisasContext * ctx) \
+static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv_i64 a0, a1, b0, b1, tmp; \
if (unlikely(!ctx->vsx_enabled)) { \
@@ -1444,7 +1444,8 @@ static void gen_##name(DisasContext *ctx) \
xb = tcg_const_tl(xB(ctx->opcode)); \
t0 = tcg_temp_new_i32(); \
t1 = tcg_temp_new_i64(); \
- /* uimm > 15 out of bound and for \
+ /* \
+ * uimm > 15 out of bound and for \
* uimm > 12 handle as per hardware in helper \
*/ \
if (uimm > 15) { \
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 20a64f3b77..0394a9ddad 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -41,12 +41,13 @@
#include "fpu/softfloat.h"
#include "qapi/qapi-commands-target.h"
-//#define PPC_DUMP_CPU
-//#define PPC_DEBUG_SPR
-//#define PPC_DUMP_SPR_ACCESSES
+/* #define PPC_DUMP_CPU */
+/* #define PPC_DEBUG_SPR */
+/* #define PPC_DUMP_SPR_ACCESSES */
/* #define USE_APPLE_GDB */
-/* Generic callbacks:
+/*
+ * Generic callbacks:
* do nothing but store/retrieve spr value
*/
static void spr_load_dump_spr(int sprn)
@@ -58,7 +59,7 @@ static void spr_load_dump_spr(int sprn)
#endif
}
-static void spr_read_generic (DisasContext *ctx, int gprn, int sprn)
+static void spr_read_generic(DisasContext *ctx, int gprn, int sprn)
{
gen_load_spr(cpu_gpr[gprn], sprn);
spr_load_dump_spr(sprn);
@@ -230,13 +231,13 @@ static void spr_read_tbu(DisasContext *ctx, int gprn, int sprn)
}
}
-__attribute__ (( unused ))
+ATTRIBUTE_UNUSED
static void spr_read_atbl(DisasContext *ctx, int gprn, int sprn)
{
gen_helper_load_atbl(cpu_gpr[gprn], cpu_env);
}
-__attribute__ (( unused ))
+ATTRIBUTE_UNUSED
static void spr_read_atbu(DisasContext *ctx, int gprn, int sprn)
{
gen_helper_load_atbu(cpu_gpr[gprn], cpu_env);
@@ -267,20 +268,20 @@ static void spr_write_tbu(DisasContext *ctx, int sprn, int gprn)
}
}
-__attribute__ (( unused ))
+ATTRIBUTE_UNUSED
static void spr_write_atbl(DisasContext *ctx, int sprn, int gprn)
{
gen_helper_store_atbl(cpu_env, cpu_gpr[gprn]);
}
-__attribute__ (( unused ))
+ATTRIBUTE_UNUSED
static void spr_write_atbu(DisasContext *ctx, int sprn, int gprn)
{
gen_helper_store_atbu(cpu_env, cpu_gpr[gprn]);
}
#if defined(TARGET_PPC64)
-__attribute__ (( unused ))
+ATTRIBUTE_UNUSED
static void spr_read_purr(DisasContext *ctx, int gprn, int sprn)
{
gen_helper_load_purr(cpu_gpr[gprn], cpu_env);
@@ -319,12 +320,16 @@ static void spr_write_hdecr(DisasContext *ctx, int sprn, int gprn)
/* IBAT0L...IBAT7L */
static void spr_read_ibat(DisasContext *ctx, int gprn, int sprn)
{
- tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
+ tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
+ offsetof(CPUPPCState,
+ IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
}
static void spr_read_ibat_h(DisasContext *ctx, int gprn, int sprn)
{
- tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][((sprn - SPR_IBAT4U) / 2) + 4]));
+ tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
+ offsetof(CPUPPCState,
+ IBAT[sprn & 1][((sprn - SPR_IBAT4U) / 2) + 4]));
}
static void spr_write_ibatu(DisasContext *ctx, int sprn, int gprn)
@@ -359,12 +364,16 @@ static void spr_write_ibatl_h(DisasContext *ctx, int sprn, int gprn)
/* DBAT0L...DBAT7L */
static void spr_read_dbat(DisasContext *ctx, int gprn, int sprn)
{
- tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2]));
+ tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
+ offsetof(CPUPPCState,
+ DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2]));
}
static void spr_read_dbat_h(DisasContext *ctx, int gprn, int sprn)
{
- tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4]));
+ tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
+ offsetof(CPUPPCState,
+ DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4]));
}
static void spr_write_dbatu(DisasContext *ctx, int sprn, int gprn)
@@ -473,7 +482,9 @@ static void spr_write_hid0_601(DisasContext *ctx, int sprn, int gprn)
#if !defined(CONFIG_USER_ONLY)
static void spr_read_601_ubat(DisasContext *ctx, int gprn, int sprn)
{
- tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
+ tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
+ offsetof(CPUPPCState,
+ IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
}
static void spr_write_601_ubatu(DisasContext *ctx, int sprn, int gprn)
@@ -532,7 +543,8 @@ static void spr_write_booke_tsr(DisasContext *ctx, int sprn, int gprn)
#if !defined(CONFIG_USER_ONLY)
static void spr_read_403_pbr(DisasContext *ctx, int gprn, int sprn)
{
- tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUPPCState, pb[sprn - SPR_403_PBL1]));
+ tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env,
+ offsetof(CPUPPCState, pb[sprn - SPR_403_PBL1]));
}
static void spr_write_403_pbr(DisasContext *ctx, int sprn, int gprn)
@@ -661,14 +673,20 @@ static inline void vscr_init(CPUPPCState *env, uint32_t val)
static inline void _spr_register(CPUPPCState *env, int num,
const char *name,
- void (*uea_read)(DisasContext *ctx, int gprn, int sprn),
- void (*uea_write)(DisasContext *ctx, int sprn, int gprn),
+ void (*uea_read)(DisasContext *ctx,
+ int gprn, int sprn),
+ void (*uea_write)(DisasContext *ctx,
+ int sprn, int gprn),
#if !defined(CONFIG_USER_ONLY)
- void (*oea_read)(DisasContext *ctx, int gprn, int sprn),
- void (*oea_write)(DisasContext *ctx, int sprn, int gprn),
- void (*hea_read)(DisasContext *opaque, int gprn, int sprn),
- void (*hea_write)(DisasContext *opaque, int sprn, int gprn),
+ void (*oea_read)(DisasContext *ctx,
+ int gprn, int sprn),
+ void (*oea_write)(DisasContext *ctx,
+ int sprn, int gprn),
+ void (*hea_read)(DisasContext *opaque,
+ int gprn, int sprn),
+ void (*hea_write)(DisasContext *opaque,
+ int sprn, int gprn),
#endif
#if defined(CONFIG_KVM)
uint64_t one_reg_id,
@@ -678,7 +696,7 @@ static inline void _spr_register(CPUPPCState *env, int num,
ppc_spr_t *spr;
spr = &env->spr_cb[num];
- if (spr->name != NULL ||env-> spr[num] != 0x00000000 ||
+ if (spr->name != NULL || env->spr[num] != 0x00000000 ||
#if !defined(CONFIG_USER_ONLY)
spr->oea_read != NULL || spr->oea_write != NULL ||
#endif
@@ -774,8 +792,10 @@ static void gen_spr_sdr1(CPUPPCState *env)
{
#ifndef CONFIG_USER_ONLY
if (env->has_hv_mode) {
- /* SDR1 is a hypervisor resource on CPUs which have a
- * hypervisor mode */
+ /*
+ * SDR1 is a hypervisor resource on CPUs which have a
+ * hypervisor mode
+ */
spr_register_hv(env, SPR_SDR1, "SDR1",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
@@ -1123,7 +1143,8 @@ static void spr_write_amr(DisasContext *ctx, int sprn, int gprn)
TCGv t1 = tcg_temp_new();
TCGv t2 = tcg_temp_new();
- /* Note, the HV=1 PR=0 case is handled earlier by simply using
+ /*
+ * Note, the HV=1 PR=0 case is handled earlier by simply using
* spr_write_generic for HV mode in the SPR table
*/
@@ -1157,7 +1178,8 @@ static void spr_write_uamor(DisasContext *ctx, int sprn, int gprn)
TCGv t1 = tcg_temp_new();
TCGv t2 = tcg_temp_new();
- /* Note, the HV=1 case is handled earlier by simply using
+ /*
+ * Note, the HV=1 case is handled earlier by simply using
* spr_write_generic for HV mode in the SPR table
*/
@@ -1187,7 +1209,8 @@ static void spr_write_iamr(DisasContext *ctx, int sprn, int gprn)
TCGv t1 = tcg_temp_new();
TCGv t2 = tcg_temp_new();
- /* Note, the HV=1 case is handled earlier by simply using
+ /*
+ * Note, the HV=1 case is handled earlier by simply using
* spr_write_generic for HV mode in the SPR table
*/
@@ -1215,10 +1238,13 @@ static void spr_write_iamr(DisasContext *ctx, int sprn, int gprn)
static void gen_spr_amr(CPUPPCState *env)
{
#ifndef CONFIG_USER_ONLY
- /* Virtual Page Class Key protection */
- /* The AMR is accessible either via SPR 13 or SPR 29. 13 is
+ /*
+ * Virtual Page Class Key protection
+ *
+ * The AMR is accessible either via SPR 13 or SPR 29. 13 is
* userspace accessible, 29 is privileged. So we only need to set
- * the kvm ONE_REG id on one of them, we use 29 */
+ * the kvm ONE_REG id on one of them, we use 29
+ */
spr_register(env, SPR_UAMR, "UAMR",
&spr_read_generic, &spr_write_amr,
&spr_read_generic, &spr_write_amr,
@@ -1902,7 +1928,8 @@ static void gen_spr_BookE206(CPUPPCState *env, uint32_t mas_mask,
/* TLB assist registers */
/* XXX : not implemented */
for (i = 0; i < 8; i++) {
- void (*uea_write)(DisasContext *ctx, int sprn, int gprn) = &spr_write_generic32;
+ void (*uea_write)(DisasContext *ctx, int sprn, int gprn) =
+ &spr_write_generic32;
if (i == 2 && (mas_mask & (1 << i)) && (env->insns_flags & PPC_64B)) {
uea_write = &spr_write_generic;
}
@@ -2798,7 +2825,6 @@ static void gen_spr_8xx(CPUPPCState *env)
0x00000000);
}
-// XXX: TODO
/*
* AMR => SPR 29 (Power 2.04)
* CTRL => SPR 136 (Power 2.04)
@@ -3344,16 +3370,18 @@ static int check_pow_nocheck(CPUPPCState *env)
static int check_pow_hid0(CPUPPCState *env)
{
- if (env->spr[SPR_HID0] & 0x00E00000)
+ if (env->spr[SPR_HID0] & 0x00E00000) {
return 1;
+ }
return 0;
}
static int check_pow_hid0_74xx(CPUPPCState *env)
{
- if (env->spr[SPR_HID0] & 0x00600000)
+ if (env->spr[SPR_HID0] & 0x00600000) {
return 1;
+ }
return 0;
}
@@ -4602,7 +4630,8 @@ POWERPC_FAMILY(e200)(ObjectClass *oc, void *data)
dc->desc = "e200 core";
pcc->init_proc = init_proc_e200;
pcc->check_pow = check_pow_hid0;
- /* XXX: unimplemented instructions:
+ /*
+ * XXX: unimplemented instructions:
* dcblc
* dcbtlst
* dcbtstls
@@ -4797,18 +4826,18 @@ static void init_proc_e500(CPUPPCState *env, int version)
* gen_spr_BookE(env, 0x0000000F0000FD7FULL);
*/
switch (version) {
- case fsl_e500v1:
- case fsl_e500v2:
- default:
- ivor_mask = 0x0000000F0000FFFFULL;
- break;
- case fsl_e500mc:
- case fsl_e5500:
- ivor_mask = 0x000003FE0000FFFFULL;
- break;
- case fsl_e6500:
- ivor_mask = 0x000003FF0000FFFFULL;
- break;
+ case fsl_e500v1:
+ case fsl_e500v2:
+ default:
+ ivor_mask = 0x0000000F0000FFFFULL;
+ break;
+ case fsl_e500mc:
+ case fsl_e5500:
+ ivor_mask = 0x000003FE0000FFFFULL;
+ break;
+ case fsl_e6500:
+ ivor_mask = 0x000003FF0000FFFFULL;
+ break;
}
gen_spr_BookE(env, ivor_mask);
gen_spr_usprg3(env);
@@ -4848,7 +4877,8 @@ static void init_proc_e500(CPUPPCState *env, int version)
tlbncfg[1] = 0x40028040;
break;
default:
- cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]);
+ cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n",
+ env->spr[SPR_PVR]);
}
#endif
/* Cache sizes */
@@ -4872,7 +4902,8 @@ static void init_proc_e500(CPUPPCState *env, int version)
l1cfg1 |= 0x0B83820;
break;
default:
- cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n", env->spr[SPR_PVR]);
+ cpu_abort(CPU(cpu), "Unknown CPU: " TARGET_FMT_lx "\n",
+ env->spr[SPR_PVR]);
}
gen_spr_BookE206(env, 0x000000DF, tlbncfg, mmucfg);
/* XXX : not implemented */
@@ -5252,7 +5283,8 @@ static void init_proc_601(CPUPPCState *env)
0x00000000);
/* Memory management */
init_excp_601(env);
- /* XXX: beware that dcache line size is 64
+ /*
+ * XXX: beware that dcache line size is 64
* but dcbz uses 32 bytes "sectors"
* XXX: this breaks clcs instruction !
*/
@@ -5789,7 +5821,8 @@ static void init_proc_750(CPUPPCState *env)
0x00000000);
/* Memory management */
gen_low_BATs(env);
- /* XXX: high BATs are also present but are known to be bugged on
+ /*
+ * XXX: high BATs are also present but are known to be bugged on
* die version 1.x
*/
init_excp_7x0(env);
@@ -5971,7 +6004,8 @@ POWERPC_FAMILY(750cl)(ObjectClass *oc, void *data)
dc->desc = "PowerPC 750 CL";
pcc->init_proc = init_proc_750cl;
pcc->check_pow = check_pow_hid0;
- /* XXX: not implemented:
+ /*
+ * XXX: not implemented:
* cache lock instructions:
* dcbz_l
* floating point paired instructions
@@ -7569,8 +7603,10 @@ static void gen_spr_book3s_altivec(CPUPPCState *env)
&spr_read_generic, &spr_write_generic,
KVM_REG_PPC_VRSAVE, 0x00000000);
- /* Can't find information on what this should be on reset. This
- * value is the one used by 74xx processors. */
+ /*
+ * Can't find information on what this should be on reset. This
+ * value is the one used by 74xx processors.
+ */
vscr_init(env, 0x00010000);
}
@@ -8975,8 +9011,9 @@ static void init_ppc_proc(PowerPCCPU *cpu)
env->irq_inputs = NULL;
/* Set all exception vectors to an invalid address */
- for (i = 0; i < POWERPC_EXCP_NB; i++)
+ for (i = 0; i < POWERPC_EXCP_NB; i++) {
env->excp_vectors[i] = (target_ulong)(-1ULL);
+ }
env->ivor_mask = 0x00000000;
env->ivpr_mask = 0x00000000;
/* Default MMU definitions */
@@ -9108,8 +9145,9 @@ static void init_ppc_proc(PowerPCCPU *cpu)
#if !defined(CONFIG_USER_ONLY)
if (env->nb_tlb != 0) {
int nb_tlb = env->nb_tlb;
- if (env->id_tlbs != 0)
+ if (env->id_tlbs != 0) {
nb_tlb *= 2;
+ }
switch (env->tlb_type) {
case TLB_6XX:
env->tlb.tlb6 = g_new0(ppc6xx_tlb_t, nb_tlb);
@@ -9201,8 +9239,9 @@ static void fill_new_table(opc_handler_t **table, int len)
{
int i;
- for (i = 0; i < len; i++)
+ for (i = 0; i < len; i++) {
table[i] = &invalid_handler;
+ }
}
static int create_new_table(opc_handler_t **table, unsigned char idx)
@@ -9219,8 +9258,9 @@ static int create_new_table(opc_handler_t **table, unsigned char idx)
static int insert_in_table(opc_handler_t **table, unsigned char idx,
opc_handler_t *handler)
{
- if (table[idx] != &invalid_handler)
+ if (table[idx] != &invalid_handler) {
return -1;
+ }
table[idx] = handler;
return 0;
@@ -9341,17 +9381,20 @@ static int register_insn(opc_handler_t **ppc_opcodes, opcode_t *insn)
}
} else {
if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
- insn->opc3, &insn->handler) < 0)
+ insn->opc3, &insn->handler) < 0) {
return -1;
+ }
}
} else {
if (register_ind_insn(ppc_opcodes, insn->opc1,
- insn->opc2, &insn->handler) < 0)
+ insn->opc2, &insn->handler) < 0) {
return -1;
+ }
}
} else {
- if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0)
+ if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0) {
return -1;
+ }
}
return 0;
@@ -9363,8 +9406,9 @@ static int test_opcode_table(opc_handler_t **table, int len)
for (i = 0, count = 0; i < len; i++) {
/* Consistency fixup */
- if (table[i] == NULL)
+ if (table[i] == NULL) {
table[i] = &invalid_handler;
+ }
if (table[i] != &invalid_handler) {
if (is_indirect_opcode(table[i])) {
tmp = test_opcode_table(ind_table(table[i]),
@@ -9386,8 +9430,9 @@ static int test_opcode_table(opc_handler_t **table, int len)
static void fix_opcode_tables(opc_handler_t **ppc_opcodes)
{
- if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0)
+ if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0) {
printf("*** WARNING: no opcode defined !\n");
+ }
}
/*****************************************************************************/
@@ -9726,14 +9771,15 @@ static int ppc_fixup_cpu(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
- /* TCG doesn't (yet) emulate some groups of instructions that
- * are implemented on some otherwise supported CPUs (e.g. VSX
- * and decimal floating point instructions on POWER7). We
- * remove unsupported instruction groups from the cpu state's
- * instruction masks and hope the guest can cope. For at
- * least the pseries machine, the unavailability of these
- * instructions can be advertised to the guest via the device
- * tree. */
+ /*
+ * TCG doesn't (yet) emulate some groups of instructions that are
+ * implemented on some otherwise supported CPUs (e.g. VSX and
+ * decimal floating point instructions on POWER7). We remove
+ * unsupported instruction groups from the cpu state's instruction
+ * masks and hope the guest can cope. For at least the pseries
+ * machine, the unavailability of these instructions can be
+ * advertised to the guest via the device tree.
+ */
if ((env->insns_flags & ~PPC_TCG_INSNS)
|| (env->insns_flags2 & ~PPC_TCG_INSNS2)) {
warn_report("Disabling some instructions which are not "
@@ -9928,31 +9974,37 @@ static void ppc_cpu_realize(DeviceState *dev, Error **errp)
" Bus model : %s\n",
excp_model, bus_model);
printf(" MSR features :\n");
- if (env->flags & POWERPC_FLAG_SPE)
+ if (env->flags & POWERPC_FLAG_SPE) {
printf(" signal processing engine enable"
"\n");
- else if (env->flags & POWERPC_FLAG_VRE)
+ } else if (env->flags & POWERPC_FLAG_VRE) {
printf(" vector processor enable\n");
- if (env->flags & POWERPC_FLAG_TGPR)
+ }
+ if (env->flags & POWERPC_FLAG_TGPR) {
printf(" temporary GPRs\n");
- else if (env->flags & POWERPC_FLAG_CE)
+ } else if (env->flags & POWERPC_FLAG_CE) {
printf(" critical input enable\n");
- if (env->flags & POWERPC_FLAG_SE)
+ }
+ if (env->flags & POWERPC_FLAG_SE) {
printf(" single-step trace mode\n");
- else if (env->flags & POWERPC_FLAG_DWE)
+ } else if (env->flags & POWERPC_FLAG_DWE) {
printf(" debug wait enable\n");
- else if (env->flags & POWERPC_FLAG_UBLE)
+ } else if (env->flags & POWERPC_FLAG_UBLE) {
printf(" user BTB lock enable\n");
- if (env->flags & POWERPC_FLAG_BE)
+ }
+ if (env->flags & POWERPC_FLAG_BE) {
printf(" branch-step trace mode\n");
- else if (env->flags & POWERPC_FLAG_DE)
+ } else if (env->flags & POWERPC_FLAG_DE) {
printf(" debug interrupt enable\n");
- if (env->flags & POWERPC_FLAG_PX)
+ }
+ if (env->flags & POWERPC_FLAG_PX) {
printf(" inclusive protection\n");
- else if (env->flags & POWERPC_FLAG_PMM)
+ } else if (env->flags & POWERPC_FLAG_PMM) {
printf(" performance monitor mark\n");
- if (env->flags == POWERPC_FLAG_NONE)
+ }
+ if (env->flags == POWERPC_FLAG_NONE) {
printf(" none\n");
+ }
printf(" Time-base/decrementer clock source: %s\n",
env->flags & POWERPC_FLAG_RTC_CLK ? "RTC clock" : "bus clock");
dump_ppc_insns(env);
@@ -10094,8 +10146,9 @@ static ObjectClass *ppc_cpu_class_by_name(const char *name)
const char *p;
unsigned long pvr;
- /* Lookup by PVR if cpu_model is valid 8 digit hex number
- * (excl: 0x prefix if present)
+ /*
+ * Lookup by PVR if cpu_model is valid 8 digit hex number (excl:
+ * 0x prefix if present)
*/
if (!qemu_strtoul(name, &p, 16, &pvr)) {
int len = p - name;
@@ -10439,14 +10492,14 @@ static void ppc_cpu_instance_init(Object *obj)
env->bfd_mach = pcc->bfd_mach;
env->check_pow = pcc->check_pow;
- /* Mark HV mode as supported if the CPU has an MSR_HV bit
- * in the msr_mask. The mask can later be cleared by PAPR
- * mode but the hv mode support will remain, thus enforcing
- * that we cannot use priv. instructions in guest in PAPR
- * mode. For 970 we currently simply don't set HV in msr_mask
- * thus simulating an "Apple mode" 970. If we ever want to
- * support 970 HV mode, we'll have to add a processor attribute
- * of some sort.
+ /*
+ * Mark HV mode as supported if the CPU has an MSR_HV bit in the
+ * msr_mask. The mask can later be cleared by PAPR mode but the hv
+ * mode support will remain, thus enforcing that we cannot use
+ * priv. instructions in guest in PAPR mode. For 970 we currently
+ * simply don't set HV in msr_mask thus simulating an "Apple mode"
+ * 970. If we ever want to support 970 HV mode, we'll have to add
+ * a processor attribute of some sort.
*/
#if !defined(CONFIG_USER_ONLY)
env->has_hv_mode = !!(env->msr_mask & MSR_HVB);
@@ -10573,7 +10626,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
cc->tcg_initialize = ppc_translate_init;
#endif
cc->disas_set_info = ppc_disas_set_info;
-
+
dc->fw_name = "PowerPC,UNKNOWN";
}
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 698dd9cb82..b58ef0a8ef 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -399,6 +399,13 @@ int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit)
return 0;
}
+void s390_set_max_pagesize(uint64_t pagesize, Error **errp)
+{
+ if (kvm_enabled()) {
+ kvm_s390_set_max_pagesize(pagesize, errp);
+ }
+}
+
void s390_cmma_reset(void)
{
if (kvm_enabled()) {
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index d8990c405a..7305cacc7b 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -734,6 +734,7 @@ static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg)
/* cpu.c */
void s390_crypto_reset(void);
int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit);
+void s390_set_max_pagesize(uint64_t pagesize, Error **errp);
void s390_cmma_reset(void);
void s390_enable_css_support(S390CPU *cpu);
int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id,
diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c
index bf7795e47a..22b4514ca6 100644
--- a/target/s390x/kvm-stub.c
+++ b/target/s390x/kvm-stub.c
@@ -93,6 +93,10 @@ int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit)
return 0;
}
+void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp)
+{
+}
+
void kvm_s390_crypto_reset(void)
{
}
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
index 2c6e35b5aa..7df7be4a1b 100644
--- a/target/s390x/kvm.c
+++ b/target/s390x/kvm.c
@@ -283,44 +283,37 @@ void kvm_s390_crypto_reset(void)
}
}
-static int kvm_s390_configure_mempath_backing(KVMState *s)
+void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp)
{
- size_t path_psize = qemu_getrampagesize();
-
- if (path_psize == 4 * KiB) {
- return 0;
+ if (pagesize == 4 * KiB) {
+ return;
}
if (!hpage_1m_allowed()) {
- error_report("This QEMU machine does not support huge page "
- "mappings");
- return -EINVAL;
+ error_setg(errp, "This QEMU machine does not support huge page "
+ "mappings");
+ return;
}
- if (path_psize != 1 * MiB) {
- error_report("Memory backing with 2G pages was specified, "
- "but KVM does not support this memory backing");
- return -EINVAL;
+ if (pagesize != 1 * MiB) {
+ error_setg(errp, "Memory backing with 2G pages was specified, "
+ "but KVM does not support this memory backing");
+ return;
}
- if (kvm_vm_enable_cap(s, KVM_CAP_S390_HPAGE_1M, 0)) {
- error_report("Memory backing with 1M pages was specified, "
- "but KVM does not support this memory backing");
- return -EINVAL;
+ if (kvm_vm_enable_cap(kvm_state, KVM_CAP_S390_HPAGE_1M, 0)) {
+ error_setg(errp, "Memory backing with 1M pages was specified, "
+ "but KVM does not support this memory backing");
+ return;
}
cap_hpage_1m = 1;
- return 0;
}
int kvm_arch_init(MachineState *ms, KVMState *s)
{
MachineClass *mc = MACHINE_GET_CLASS(ms);
- if (kvm_s390_configure_mempath_backing(s)) {
- return -EINVAL;
- }
-
mc->default_cpu_type = S390_CPU_TYPE_NAME("host");
cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS);
cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF);
diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h
index 6e52287da3..caf985955b 100644
--- a/target/s390x/kvm_s390x.h
+++ b/target/s390x/kvm_s390x.h
@@ -36,6 +36,7 @@ int kvm_s390_cmma_active(void);
void kvm_s390_cmma_reset(void);
void kvm_s390_reset_vcpu(S390CPU *cpu);
int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit);
+void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp);
void kvm_s390_crypto_reset(void);
void kvm_s390_restart_interrupt(S390CPU *cpu);
void kvm_s390_stop_interrupt(S390CPU *cpu);
diff --git a/tests/acceptance/empty_cpu_model.py b/tests/acceptance/empty_cpu_model.py
new file mode 100644
index 0000000000..3f4f663582
--- /dev/null
+++ b/tests/acceptance/empty_cpu_model.py
@@ -0,0 +1,19 @@
+# Check for crash when using empty -cpu option
+#
+# Copyright (c) 2019 Red Hat, Inc.
+#
+# Author:
+# Eduardo Habkost <ehabkost@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later. See the COPYING file in the top-level directory.
+import subprocess
+from avocado_qemu import Test
+
+class EmptyCPUModel(Test):
+ def test(self):
+ cmd = [self.qemu_bin, '-S', '-display', 'none', '-machine', 'none', '-cpu', '']
+ r = subprocess.run(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+ self.assertEquals(r.returncode, 1, "QEMU exit code should be 1")
+ self.assertEquals(r.stdout, b'', "QEMU stdout should be empty")
+ self.assertNotEquals(r.stderr, b'', "QEMU stderr shouldn't be empty")
diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c
index c591748aaf..24852d4c7d 100644
--- a/tests/boot-serial-test.c
+++ b/tests/boot-serial-test.c
@@ -114,7 +114,7 @@ static testdef_t tests[] = {
{ "sparc", "SS-4", "", "MB86904" },
{ "sparc", "SS-600MP", "", "TMS390Z55" },
{ "sparc64", "sun4u", "", "UltraSPARC" },
- { "s390x", "s390-ccw-virtio", "", "virtio device" },
+ { "s390x", "s390-ccw-virtio", "", "device" },
{ "m68k", "mcf5208evb", "", "TT", sizeof(kernel_mcf5208), kernel_mcf5208 },
{ "microblaze", "petalogix-s3adsp1800", "", "TT",
sizeof(kernel_pls3adsp1800), kernel_pls3adsp1800 },
diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c
index 8565885420..f7f177d0ea 100644
--- a/util/mmap-alloc.c
+++ b/util/mmap-alloc.c
@@ -10,6 +10,13 @@
* later. See the COPYING file in the top-level directory.
*/
+#ifdef CONFIG_LINUX
+#include <linux/mman.h>
+#else /* !CONFIG_LINUX */
+#define MAP_SYNC 0x0
+#define MAP_SHARED_VALIDATE 0x0
+#endif /* CONFIG_LINUX */
+
#include "qemu/osdep.h"
#include "qemu/mmap-alloc.h"
#include "qemu/host-utils.h"
@@ -75,9 +82,14 @@ size_t qemu_mempath_getpagesize(const char *mem_path)
return getpagesize();
}
-void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared)
+void *qemu_ram_mmap(int fd,
+ size_t size,
+ size_t align,
+ bool shared,
+ bool is_pmem)
{
int flags;
+ int map_sync_flags = 0;
int guardfd;
size_t offset;
size_t pagesize;
@@ -128,9 +140,40 @@ void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared)
flags = MAP_FIXED;
flags |= fd == -1 ? MAP_ANONYMOUS : 0;
flags |= shared ? MAP_SHARED : MAP_PRIVATE;
+ if (shared && is_pmem) {
+ map_sync_flags = MAP_SYNC | MAP_SHARED_VALIDATE;
+ }
+
offset = QEMU_ALIGN_UP((uintptr_t)guardptr, align) - (uintptr_t)guardptr;
- ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE, flags, fd, 0);
+ ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE,
+ flags | map_sync_flags, fd, 0);
+
+ if (ptr == MAP_FAILED && map_sync_flags) {
+ if (errno == ENOTSUP) {
+ char *proc_link, *file_name;
+ int len;
+ proc_link = g_strdup_printf("/proc/self/fd/%d", fd);
+ file_name = g_malloc0(PATH_MAX);
+ len = readlink(proc_link, file_name, PATH_MAX - 1);
+ if (len < 0) {
+ len = 0;
+ }
+ file_name[len] = '\0';
+ fprintf(stderr, "Warning: requesting persistence across crashes "
+ "for backend file %s failed. Proceeding without "
+ "persistence, data might become corrupted in case of host "
+ "crash.\n", file_name);
+ g_free(proc_link);
+ g_free(file_name);
+ }
+ /*
+ * if map failed with MAP_SHARED_VALIDATE | MAP_SYNC,
+ * we will remove these flags to handle compatibility.
+ */
+ ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE,
+ flags, fd, 0);
+ }
if (ptr == MAP_FAILED) {
munmap(guardptr, total);
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 88dda9cd39..d97b1717d5 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -203,7 +203,7 @@ void *qemu_memalign(size_t alignment, size_t size)
void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment, bool shared)
{
size_t align = QEMU_VMALLOC_ALIGN;
- void *ptr = qemu_ram_mmap(-1, size, align, shared);
+ void *ptr = qemu_ram_mmap(-1, size, align, shared, false);
if (ptr == MAP_FAILED) {
return NULL;
diff --git a/vl.c b/vl.c
index ff5dfb6fbc..4019a4387d 100644
--- a/vl.c
+++ b/vl.c
@@ -1465,45 +1465,34 @@ static int usb_parse(const char *cmdline)
MachineState *current_machine;
-static MachineClass *find_machine(const char *name)
+static MachineClass *find_machine(const char *name, GSList *machines)
{
- GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false);
- MachineClass *mc = NULL;
+ GSList *el;
for (el = machines; el; el = el->next) {
- MachineClass *temp = el->data;
+ MachineClass *mc = el->data;
- if (!strcmp(temp->name, name)) {
- mc = temp;
- break;
- }
- if (temp->alias &&
- !strcmp(temp->alias, name)) {
- mc = temp;
- break;
+ if (!strcmp(mc->name, name) || !g_strcmp0(mc->alias, name)) {
+ return mc;
}
}
- g_slist_free(machines);
- return mc;
+ return NULL;
}
-MachineClass *find_default_machine(void)
+static MachineClass *find_default_machine(GSList *machines)
{
- GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false);
- MachineClass *mc = NULL;
+ GSList *el;
for (el = machines; el; el = el->next) {
- MachineClass *temp = el->data;
+ MachineClass *mc = el->data;
- if (temp->is_default) {
- mc = temp;
- break;
+ if (mc->is_default) {
+ return mc;
}
}
- g_slist_free(machines);
- return mc;
+ return NULL;
}
MachineInfoList *qmp_query_machines(Error **errp)
@@ -2585,22 +2574,12 @@ static gint machine_class_cmp(gconstpointer a, gconstpointer b)
object_class_get_name(OBJECT_CLASS(mc1)));
}
- static MachineClass *machine_parse(const char *name)
+static MachineClass *machine_parse(const char *name, GSList *machines)
{
- MachineClass *mc = NULL;
- GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false);
+ MachineClass *mc;
+ GSList *el;
- if (name) {
- mc = find_machine(name);
- }
- if (mc) {
- g_slist_free(machines);
- return mc;
- }
- if (name && !is_help_option(name)) {
- error_report("unsupported machine type");
- error_printf("Use -machine help to list supported machines\n");
- } else {
+ if (is_help_option(name)) {
printf("Supported machines are:\n");
machines = g_slist_sort(machines, machine_class_cmp);
for (el = machines; el; el = el->next) {
@@ -2612,10 +2591,16 @@ static gint machine_class_cmp(gconstpointer a, gconstpointer b)
mc->is_default ? " (default)" : "",
mc->deprecation_reason ? " (deprecated)" : "");
}
+ exit(0);
}
- g_slist_free(machines);
- exit(!name || !is_help_option(name));
+ mc = find_machine(name, machines);
+ if (!mc) {
+ error_report("unsupported machine type");
+ error_printf("Use -machine help to list supported machines\n");
+ exit(1);
+ }
+ return mc;
}
void qemu_add_exit_notifier(Notifier *notify)
@@ -2706,7 +2691,8 @@ static const QEMUOption *lookup_opt(int argc, char **argv,
static MachineClass *select_machine(void)
{
- MachineClass *machine_class = find_default_machine();
+ GSList *machines = object_class_get_list(TYPE_MACHINE, false);
+ MachineClass *machine_class = find_default_machine(machines);
const char *optarg;
QemuOpts *opts;
Location loc;
@@ -2718,7 +2704,7 @@ static MachineClass *select_machine(void)
optarg = qemu_opt_get(opts, "type");
if (optarg) {
- machine_class = machine_parse(optarg);
+ machine_class = machine_parse(optarg, machines);
}
if (!machine_class) {
@@ -2728,6 +2714,7 @@ static MachineClass *select_machine(void)
}
loc_pop(&loc);
+ g_slist_free(machines);
return machine_class;
}
@@ -3002,7 +2989,7 @@ int main(int argc, char **argv, char **envp)
const char *optarg;
const char *loadvm = NULL;
MachineClass *machine_class;
- const char *cpu_model;
+ const char *cpu_option;
const char *vga_model = NULL;
const char *qtest_chrdev = NULL;
const char *qtest_log = NULL;
@@ -3081,7 +3068,7 @@ int main(int argc, char **argv, char **envp)
QLIST_INIT (&vm_change_state_head);
os_setup_early_signal_handling();
- cpu_model = NULL;
+ cpu_option = NULL;
snapshot = 0;
nb_nics = 0;
@@ -3133,7 +3120,7 @@ int main(int argc, char **argv, char **envp)
switch(popt->index) {
case QEMU_OPTION_cpu:
/* hw initialization will check this */
- cpu_model = optarg;
+ cpu_option = optarg;
break;
case QEMU_OPTION_hda:
case QEMU_OPTION_hdb:
@@ -4050,8 +4037,8 @@ int main(int argc, char **argv, char **envp)
qemu_set_hw_version(machine_class->hw_version);
}
- if (cpu_model && is_help_option(cpu_model)) {
- list_cpus(cpu_model);
+ if (cpu_option && is_help_option(cpu_option)) {
+ list_cpus(cpu_option);
exit(0);
}
@@ -4299,9 +4286,9 @@ int main(int argc, char **argv, char **envp)
* Global properties get set up by qdev_prop_register_global(),
* called from user_register_global_props(), and certain option
* desugaring. Also in CPU feature desugaring (buried in
- * parse_cpu_model()), which happens below this point, but may
+ * parse_cpu_option()), which happens below this point, but may
* only target the CPU type, which can only be created after
- * parse_cpu_model() returned the type.
+ * parse_cpu_option() returned the type.
*
* Machine compat properties: object_set_machine_compat_props().
* Accelerator compat props: object_set_accelerator_compat_props(),
@@ -4465,8 +4452,8 @@ int main(int argc, char **argv, char **envp)
/* parse features once if machine provides default cpu_type */
current_machine->cpu_type = machine_class->default_cpu_type;
- if (cpu_model) {
- current_machine->cpu_type = parse_cpu_model(cpu_model);
+ if (cpu_option) {
+ current_machine->cpu_type = parse_cpu_option(cpu_option);
}
parse_numa_opts(current_machine);