You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'char-misc-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH: "Here is the big char/misc driver patchset for 4.11-rc1. Lots of different driver subsystems updated here: rework for the hyperv subsystem to handle new platforms better, mei and w1 and extcon driver updates, as well as a number of other "minor" driver updates. All of these have been in linux-next for a while with no reported issues" * tag 'char-misc-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (169 commits) goldfish: Sanitize the broken interrupt handler x86/platform/goldfish: Prevent unconditional loading vmbus: replace modulus operation with subtraction vmbus: constify parameters where possible vmbus: expose hv_begin/end_read vmbus: remove conditional locking of vmbus_write vmbus: add direct isr callback mode vmbus: change to per channel tasklet vmbus: put related per-cpu variable together vmbus: callback is in softirq not workqueue binder: Add support for file-descriptor arrays binder: Add support for scatter-gather binder: Add extra size to allocator binder: Refactor binder_transact() binder: Support multiple /dev instances binder: Deal with contexts in debugfs binder: Support multiple context managers binder: Split flat_binder_object auxdisplay: ht16k33: remove private workqueue auxdisplay: ht16k33: rework input device initialization ...
This commit is contained in:
@@ -11,7 +11,7 @@ DOCBOOKS := z8530book.xml \
|
|||||||
writing_usb_driver.xml networking.xml \
|
writing_usb_driver.xml networking.xml \
|
||||||
kernel-api.xml filesystems.xml lsm.xml kgdb.xml \
|
kernel-api.xml filesystems.xml lsm.xml kgdb.xml \
|
||||||
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
|
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
|
||||||
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
|
genericirq.xml s390-drivers.xml scsi.xml \
|
||||||
sh.xml regulator.xml w1.xml \
|
sh.xml regulator.xml w1.xml \
|
||||||
writing_musb_glue_layer.xml iio.xml
|
writing_musb_glue_layer.xml iio.xml
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1195,6 +1195,10 @@
|
|||||||
When zero, profiling data is discarded and associated
|
When zero, profiling data is discarded and associated
|
||||||
debugfs files are removed at module unload time.
|
debugfs files are removed at module unload time.
|
||||||
|
|
||||||
|
goldfish [X86] Enable the goldfish android emulator platform.
|
||||||
|
Don't use this when you are not running on the
|
||||||
|
android emulator
|
||||||
|
|
||||||
gpt [EFI] Forces disk with valid GPT signature but
|
gpt [EFI] Forces disk with valid GPT signature but
|
||||||
invalid Protective MBR to be treated as GPT. If the
|
invalid Protective MBR to be treated as GPT. If the
|
||||||
primary GPT is corrupted, it enables the backup/alternate
|
primary GPT is corrupted, it enables the backup/alternate
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
EEPROM / CSR SMBus-slave interface of IDT 89HPESx devices
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible : should be "<manufacturer>,<type>"
|
||||||
|
Basically there is only one manufacturer: idt, but some
|
||||||
|
compatible devices may be produced in future. Following devices
|
||||||
|
are supported: 89hpes8nt2, 89hpes12nt3, 89hpes24nt6ag2,
|
||||||
|
89hpes32nt8ag2, 89hpes32nt8bg2, 89hpes12nt12g2, 89hpes16nt16g2,
|
||||||
|
89hpes24nt24g2, 89hpes32nt24ag2, 89hpes32nt24bg2;
|
||||||
|
89hpes12n3, 89hpes12n3a, 89hpes24n3, 89hpes24n3a;
|
||||||
|
89hpes32h8, 89hpes32h8g2, 89hpes48h12, 89hpes48h12g2,
|
||||||
|
89hpes48h12ag2, 89hpes16h16, 89hpes22h16, 89hpes22h16g2,
|
||||||
|
89hpes34h16, 89hpes34h16g2, 89hpes64h16, 89hpes64h16g2,
|
||||||
|
89hpes64h16ag2;
|
||||||
|
89hpes12t3g2, 89hpes24t3g2, 89hpes16t4, 89hpes4t4g2,
|
||||||
|
89hpes10t4g2, 89hpes16t4g2, 89hpes16t4ag2, 89hpes5t5,
|
||||||
|
89hpes6t5, 89hpes8t5, 89hpes8t5a, 89hpes24t6, 89hpes6t6g2,
|
||||||
|
89hpes24t6g2, 89hpes16t7, 89hpes32t8, 89hpes32t8g2,
|
||||||
|
89hpes48t12, 89hpes48t12g2.
|
||||||
|
- reg : I2C address of the IDT 89HPESx device.
|
||||||
|
|
||||||
|
Optionally there can be EEPROM-compatible subnode:
|
||||||
|
- compatible: There are five EEPROM devices supported: 24c32, 24c64, 24c128,
|
||||||
|
24c256 and 24c512 differed by size.
|
||||||
|
- reg: Custom address of EEPROM device (If not specified IDT 89HPESx
|
||||||
|
(optional) device will try to communicate with EEPROM sited by default
|
||||||
|
address - 0x50)
|
||||||
|
- read-only : Parameterless property disables writes to the EEPROM
|
||||||
|
(optional)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
idt@60 {
|
||||||
|
compatible = "idt,89hpes32nt8ag2";
|
||||||
|
reg = <0x74>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
eeprom@50 {
|
||||||
|
compatible = "onsemi,24c64";
|
||||||
|
reg = <0x50>;
|
||||||
|
read-only;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
Freescale i.MX6 On-Chip OTP Controller (OCOTP) device tree bindings
|
Freescale i.MX6 On-Chip OTP Controller (OCOTP) device tree bindings
|
||||||
|
|
||||||
This binding represents the on-chip eFuse OTP controller found on
|
This binding represents the on-chip eFuse OTP controller found on
|
||||||
i.MX6Q/D, i.MX6DL/S, i.MX6SL, and i.MX6SX SoCs.
|
i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX and i.MX6UL SoCs.
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible: should be one of
|
- compatible: should be one of
|
||||||
"fsl,imx6q-ocotp" (i.MX6Q/D/DL/S),
|
"fsl,imx6q-ocotp" (i.MX6Q/D/DL/S),
|
||||||
"fsl,imx6sl-ocotp" (i.MX6SL), or
|
"fsl,imx6sl-ocotp" (i.MX6SL), or
|
||||||
"fsl,imx6sx-ocotp" (i.MX6SX), followed by "syscon".
|
"fsl,imx6sx-ocotp" (i.MX6SX),
|
||||||
|
"fsl,imx6ul-ocotp" (i.MX6UL),
|
||||||
|
followed by "syscon".
|
||||||
- reg: Should contain the register base and length.
|
- reg: Should contain the register base and length.
|
||||||
- clocks: Should contain a phandle pointing to the gated peripheral clock.
|
- clocks: Should contain a phandle pointing to the gated peripheral clock.
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,12 @@ Optional properties in the area nodes:
|
|||||||
and in use by another device or devices
|
and in use by another device or devices
|
||||||
- export : indicates that the reserved SRAM area may be accessed outside
|
- export : indicates that the reserved SRAM area may be accessed outside
|
||||||
of the kernel, e.g. by bootloader or userspace
|
of the kernel, e.g. by bootloader or userspace
|
||||||
|
- protect-exec : Same as 'pool' above but with the additional
|
||||||
|
constraint that code wil be run from the region and
|
||||||
|
that the memory is maintained as read-only, executable
|
||||||
|
during code execution. NOTE: This region must be page
|
||||||
|
aligned on start and end in order to properly allow
|
||||||
|
manipulation of the page attributes.
|
||||||
- label : the name for the reserved partition, if omitted, the label
|
- label : the name for the reserved partition, if omitted, the label
|
||||||
is taken from the node name excluding the unit address.
|
is taken from the node name excluding the unit address.
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ available subsections can be seen below.
|
|||||||
miscellaneous
|
miscellaneous
|
||||||
vme
|
vme
|
||||||
80211/index
|
80211/index
|
||||||
|
uio-howto
|
||||||
|
|
||||||
.. only:: subproject and html
|
.. only:: subproject and html
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
|||||||
|
Intel INT3496 ACPI device extcon driver documentation
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
The Intel INT3496 ACPI device extcon driver is a driver for ACPI
|
||||||
|
devices with an acpi-id of INT3496, such as found for example on
|
||||||
|
Intel Baytrail and Cherrytrail tablets.
|
||||||
|
|
||||||
|
This ACPI device describes how the OS can read the id-pin of the devices'
|
||||||
|
USB-otg port, as well as how it optionally can enable Vbus output on the
|
||||||
|
otg port and how it can optionally control the muxing of the data pins
|
||||||
|
between an USB host and an USB peripheral controller.
|
||||||
|
|
||||||
|
The ACPI devices exposes this functionality by returning an array with up
|
||||||
|
to 3 gpio descriptors from its ACPI _CRS (Current Resource Settings) call:
|
||||||
|
|
||||||
|
Index 0: The input gpio for the id-pin, this is always present and valid
|
||||||
|
Index 1: The output gpio for enabling Vbus output from the device to the otg
|
||||||
|
port, write 1 to enable the Vbus output (this gpio descriptor may
|
||||||
|
be absent or invalid)
|
||||||
|
Index 2: The output gpio for muxing of the data pins between the USB host and
|
||||||
|
the USB peripheral controller, write 1 to mux to the peripheral
|
||||||
|
controller
|
||||||
@@ -22,7 +22,16 @@ To program the FPGA from a file or from a buffer:
|
|||||||
struct fpga_image_info *info,
|
struct fpga_image_info *info,
|
||||||
const char *buf, size_t count);
|
const char *buf, size_t count);
|
||||||
|
|
||||||
Load the FPGA from an image which exists as a buffer in memory.
|
Load the FPGA from an image which exists as a contiguous buffer in
|
||||||
|
memory. Allocating contiguous kernel memory for the buffer should be avoided,
|
||||||
|
users are encouraged to use the _sg interface instead of this.
|
||||||
|
|
||||||
|
int fpga_mgr_buf_load_sg(struct fpga_manager *mgr,
|
||||||
|
struct fpga_image_info *info,
|
||||||
|
struct sg_table *sgt);
|
||||||
|
|
||||||
|
Load the FPGA from an image from non-contiguous in memory. Callers can
|
||||||
|
construct a sg_table using alloc_page backed memory.
|
||||||
|
|
||||||
int fpga_mgr_firmware_load(struct fpga_manager *mgr,
|
int fpga_mgr_firmware_load(struct fpga_manager *mgr,
|
||||||
struct fpga_image_info *info,
|
struct fpga_image_info *info,
|
||||||
@@ -166,7 +175,7 @@ success or negative error codes otherwise.
|
|||||||
|
|
||||||
The programming sequence is:
|
The programming sequence is:
|
||||||
1. .write_init
|
1. .write_init
|
||||||
2. .write (may be called once or multiple times)
|
2. .write or .write_sg (may be called once or multiple times)
|
||||||
3. .write_complete
|
3. .write_complete
|
||||||
|
|
||||||
The .write_init function will prepare the FPGA to receive the image data. The
|
The .write_init function will prepare the FPGA to receive the image data. The
|
||||||
@@ -176,7 +185,11 @@ buffer up at least this much before starting.
|
|||||||
|
|
||||||
The .write function writes a buffer to the FPGA. The buffer may be contain the
|
The .write function writes a buffer to the FPGA. The buffer may be contain the
|
||||||
whole FPGA image or may be a smaller chunk of an FPGA image. In the latter
|
whole FPGA image or may be a smaller chunk of an FPGA image. In the latter
|
||||||
case, this function is called multiple times for successive chunks.
|
case, this function is called multiple times for successive chunks. This interface
|
||||||
|
is suitable for drivers which use PIO.
|
||||||
|
|
||||||
|
The .write_sg version behaves the same as .write except the input is a sg_table
|
||||||
|
scatter list. This interface is suitable for drivers which use DMA.
|
||||||
|
|
||||||
The .write_complete function is called after all the image has been written
|
The .write_complete function is called after all the image has been written
|
||||||
to put the FPGA into operating mode.
|
to put the FPGA into operating mode.
|
||||||
|
|||||||
+2
-1
@@ -5993,6 +5993,7 @@ S: Maintained
|
|||||||
F: arch/x86/include/asm/mshyperv.h
|
F: arch/x86/include/asm/mshyperv.h
|
||||||
F: arch/x86/include/uapi/asm/hyperv.h
|
F: arch/x86/include/uapi/asm/hyperv.h
|
||||||
F: arch/x86/kernel/cpu/mshyperv.c
|
F: arch/x86/kernel/cpu/mshyperv.c
|
||||||
|
F: arch/x86/hyperv
|
||||||
F: drivers/hid/hid-hyperv.c
|
F: drivers/hid/hid-hyperv.c
|
||||||
F: drivers/hv/
|
F: drivers/hv/
|
||||||
F: drivers/input/serio/hyperv-keyboard.c
|
F: drivers/input/serio/hyperv-keyboard.c
|
||||||
@@ -13071,7 +13072,7 @@ USERSPACE I/O (UIO)
|
|||||||
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
|
||||||
F: Documentation/DocBook/uio-howto.tmpl
|
F: Documentation/driver-api/uio-howto.rst
|
||||||
F: drivers/uio/
|
F: drivers/uio/
|
||||||
F: include/linux/uio*.h
|
F: include/linux/uio*.h
|
||||||
|
|
||||||
|
|||||||
@@ -557,15 +557,7 @@ static struct clk_lookup da850_clks[] = {
|
|||||||
CLK("da830-mmc.0", NULL, &mmcsd0_clk),
|
CLK("da830-mmc.0", NULL, &mmcsd0_clk),
|
||||||
CLK("da830-mmc.1", NULL, &mmcsd1_clk),
|
CLK("da830-mmc.1", NULL, &mmcsd1_clk),
|
||||||
CLK("ti-aemif", NULL, &aemif_clk),
|
CLK("ti-aemif", NULL, &aemif_clk),
|
||||||
/*
|
CLK("davinci-nand.0", "aemif", &aemif_nand_clk),
|
||||||
* The only user of this clock is davinci_nand and it get's it through
|
|
||||||
* con_id. The nand node itself is created from within the aemif
|
|
||||||
* driver to guarantee that it's probed after the aemif timing
|
|
||||||
* parameters are configured. of_dev_auxdata is not accessible from
|
|
||||||
* the aemif driver and can't be passed to of_platform_populate(). For
|
|
||||||
* that reason we're leaving the dev_id here as NULL.
|
|
||||||
*/
|
|
||||||
CLK(NULL, "aemif", &aemif_nand_clk),
|
|
||||||
CLK("ohci-da8xx", "usb11", &usb11_clk),
|
CLK("ohci-da8xx", "usb11", &usb11_clk),
|
||||||
CLK("musb-da8xx", "usb20", &usb20_clk),
|
CLK("musb-da8xx", "usb20", &usb20_clk),
|
||||||
CLK("spi_davinci.0", NULL, &spi0_clk),
|
CLK("spi_davinci.0", NULL, &spi0_clk),
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/irqdomain.h>
|
#include <linux/irqdomain.h>
|
||||||
|
#include <linux/platform_data/ti-aemif.h>
|
||||||
|
|
||||||
#include <asm/mach/arch.h>
|
#include <asm/mach/arch.h>
|
||||||
|
|
||||||
@@ -18,6 +19,15 @@
|
|||||||
#include "cp_intc.h"
|
#include "cp_intc.h"
|
||||||
#include <mach/da8xx.h>
|
#include <mach/da8xx.h>
|
||||||
|
|
||||||
|
static struct of_dev_auxdata da850_aemif_auxdata_lookup[] = {
|
||||||
|
OF_DEV_AUXDATA("ti,davinci-nand", 0x62000000, "davinci-nand.0", NULL),
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct aemif_platform_data aemif_data = {
|
||||||
|
.dev_lookup = da850_aemif_auxdata_lookup,
|
||||||
|
};
|
||||||
|
|
||||||
static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
|
static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
|
||||||
OF_DEV_AUXDATA("ti,davinci-i2c", 0x01c22000, "i2c_davinci.1", NULL),
|
OF_DEV_AUXDATA("ti,davinci-i2c", 0x01c22000, "i2c_davinci.1", NULL),
|
||||||
OF_DEV_AUXDATA("ti,davinci-i2c", 0x01e28000, "i2c_davinci.2", NULL),
|
OF_DEV_AUXDATA("ti,davinci-i2c", 0x01e28000, "i2c_davinci.2", NULL),
|
||||||
@@ -37,7 +47,7 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
|
|||||||
OF_DEV_AUXDATA("ti,davinci-dm6467-emac", 0x01e20000, "davinci_emac.1",
|
OF_DEV_AUXDATA("ti,davinci-dm6467-emac", 0x01e20000, "davinci_emac.1",
|
||||||
NULL),
|
NULL),
|
||||||
OF_DEV_AUXDATA("ti,da830-mcasp-audio", 0x01d00000, "davinci-mcasp.0", NULL),
|
OF_DEV_AUXDATA("ti,da830-mcasp-audio", 0x01d00000, "davinci-mcasp.0", NULL),
|
||||||
OF_DEV_AUXDATA("ti,da850-aemif", 0x68000000, "ti-aemif", NULL),
|
OF_DEV_AUXDATA("ti,da850-aemif", 0x68000000, "ti-aemif", &aemif_data),
|
||||||
OF_DEV_AUXDATA("ti,da850-tilcdc", 0x01e13000, "da8xx_lcdc.0", NULL),
|
OF_DEV_AUXDATA("ti,da850-tilcdc", 0x01e13000, "da8xx_lcdc.0", NULL),
|
||||||
OF_DEV_AUXDATA("ti,da830-ohci", 0x01e25000, "ohci-da8xx", NULL),
|
OF_DEV_AUXDATA("ti,da830-ohci", 0x01e25000, "ohci-da8xx", NULL),
|
||||||
OF_DEV_AUXDATA("ti,da830-musb", 0x01e00000, "musb-da8xx", NULL),
|
OF_DEV_AUXDATA("ti,da830-musb", 0x01e00000, "musb-da8xx", NULL),
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ obj-$(CONFIG_KVM) += kvm/
|
|||||||
# Xen paravirtualization support
|
# Xen paravirtualization support
|
||||||
obj-$(CONFIG_XEN) += xen/
|
obj-$(CONFIG_XEN) += xen/
|
||||||
|
|
||||||
|
# Hyper-V paravirtualization support
|
||||||
|
obj-$(CONFIG_HYPERVISOR_GUEST) += hyperv/
|
||||||
|
|
||||||
# lguest paravirtualization support
|
# lguest paravirtualization support
|
||||||
obj-$(CONFIG_LGUEST_GUEST) += lguest/
|
obj-$(CONFIG_LGUEST_GUEST) += lguest/
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
obj-y := hv_init.o
|
||||||
@@ -0,0 +1,277 @@
|
|||||||
|
/*
|
||||||
|
* X86 specific Hyper-V initialization code.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016, Microsoft, Inc.
|
||||||
|
*
|
||||||
|
* Author : K. Y. Srinivasan <kys@microsoft.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 as published
|
||||||
|
* by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||||
|
* NON INFRINGEMENT. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <asm/hypervisor.h>
|
||||||
|
#include <asm/hyperv.h>
|
||||||
|
#include <asm/mshyperv.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/clockchips.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
|
||||||
|
static struct ms_hyperv_tsc_page *tsc_pg;
|
||||||
|
|
||||||
|
static u64 read_hv_clock_tsc(struct clocksource *arg)
|
||||||
|
{
|
||||||
|
u64 current_tick;
|
||||||
|
|
||||||
|
if (tsc_pg->tsc_sequence != 0) {
|
||||||
|
/*
|
||||||
|
* Use the tsc page to compute the value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
u64 tmp;
|
||||||
|
u32 sequence = tsc_pg->tsc_sequence;
|
||||||
|
u64 cur_tsc;
|
||||||
|
u64 scale = tsc_pg->tsc_scale;
|
||||||
|
s64 offset = tsc_pg->tsc_offset;
|
||||||
|
|
||||||
|
rdtscll(cur_tsc);
|
||||||
|
/* current_tick = ((cur_tsc *scale) >> 64) + offset */
|
||||||
|
asm("mulq %3"
|
||||||
|
: "=d" (current_tick), "=a" (tmp)
|
||||||
|
: "a" (cur_tsc), "r" (scale));
|
||||||
|
|
||||||
|
current_tick += offset;
|
||||||
|
if (tsc_pg->tsc_sequence == sequence)
|
||||||
|
return current_tick;
|
||||||
|
|
||||||
|
if (tsc_pg->tsc_sequence != 0)
|
||||||
|
continue;
|
||||||
|
/*
|
||||||
|
* Fallback using MSR method.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
|
||||||
|
return current_tick;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct clocksource hyperv_cs_tsc = {
|
||||||
|
.name = "hyperv_clocksource_tsc_page",
|
||||||
|
.rating = 400,
|
||||||
|
.read = read_hv_clock_tsc,
|
||||||
|
.mask = CLOCKSOURCE_MASK(64),
|
||||||
|
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static u64 read_hv_clock_msr(struct clocksource *arg)
|
||||||
|
{
|
||||||
|
u64 current_tick;
|
||||||
|
/*
|
||||||
|
* Read the partition counter to get the current tick count. This count
|
||||||
|
* is set to 0 when the partition is created and is incremented in
|
||||||
|
* 100 nanosecond units.
|
||||||
|
*/
|
||||||
|
rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
|
||||||
|
return current_tick;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct clocksource hyperv_cs_msr = {
|
||||||
|
.name = "hyperv_clocksource_msr",
|
||||||
|
.rating = 400,
|
||||||
|
.read = read_hv_clock_msr,
|
||||||
|
.mask = CLOCKSOURCE_MASK(64),
|
||||||
|
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *hypercall_pg;
|
||||||
|
struct clocksource *hyperv_cs;
|
||||||
|
EXPORT_SYMBOL_GPL(hyperv_cs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is to be invoked early in the boot sequence after the
|
||||||
|
* hypervisor has been detected.
|
||||||
|
*
|
||||||
|
* 1. Setup the hypercall page.
|
||||||
|
* 2. Register Hyper-V specific clocksource.
|
||||||
|
*/
|
||||||
|
void hyperv_init(void)
|
||||||
|
{
|
||||||
|
u64 guest_id;
|
||||||
|
union hv_x64_msr_hypercall_contents hypercall_msr;
|
||||||
|
|
||||||
|
if (x86_hyper != &x86_hyper_ms_hyperv)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the hypercall page and enable hypercalls.
|
||||||
|
* 1. Register the guest ID
|
||||||
|
* 2. Enable the hypercall and register the hypercall page
|
||||||
|
*/
|
||||||
|
guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);
|
||||||
|
wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
|
||||||
|
|
||||||
|
hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
|
||||||
|
if (hypercall_pg == NULL) {
|
||||||
|
wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
|
||||||
|
hypercall_msr.enable = 1;
|
||||||
|
hypercall_msr.guest_physical_address = vmalloc_to_pfn(hypercall_pg);
|
||||||
|
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Register Hyper-V specific clocksource.
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
|
||||||
|
union hv_x64_msr_hypercall_contents tsc_msr;
|
||||||
|
|
||||||
|
tsc_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
|
||||||
|
if (!tsc_pg)
|
||||||
|
goto register_msr_cs;
|
||||||
|
|
||||||
|
hyperv_cs = &hyperv_cs_tsc;
|
||||||
|
|
||||||
|
rdmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
|
||||||
|
|
||||||
|
tsc_msr.enable = 1;
|
||||||
|
tsc_msr.guest_physical_address = vmalloc_to_pfn(tsc_pg);
|
||||||
|
|
||||||
|
wrmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
|
||||||
|
clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* For 32 bit guests just use the MSR based mechanism for reading
|
||||||
|
* the partition counter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
register_msr_cs:
|
||||||
|
hyperv_cs = &hyperv_cs_msr;
|
||||||
|
if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
|
||||||
|
clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine is called before kexec/kdump, it does the required cleanup.
|
||||||
|
*/
|
||||||
|
void hyperv_cleanup(void)
|
||||||
|
{
|
||||||
|
union hv_x64_msr_hypercall_contents hypercall_msr;
|
||||||
|
|
||||||
|
/* Reset our OS id */
|
||||||
|
wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
|
||||||
|
|
||||||
|
/* Reset the hypercall page */
|
||||||
|
hypercall_msr.as_uint64 = 0;
|
||||||
|
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
|
||||||
|
|
||||||
|
/* Reset the TSC page */
|
||||||
|
hypercall_msr.as_uint64 = 0;
|
||||||
|
wrmsrl(HV_X64_MSR_REFERENCE_TSC, hypercall_msr.as_uint64);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(hyperv_cleanup);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hv_do_hypercall- Invoke the specified hypercall
|
||||||
|
*/
|
||||||
|
u64 hv_do_hypercall(u64 control, void *input, void *output)
|
||||||
|
{
|
||||||
|
u64 input_address = (input) ? virt_to_phys(input) : 0;
|
||||||
|
u64 output_address = (output) ? virt_to_phys(output) : 0;
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
u64 hv_status = 0;
|
||||||
|
|
||||||
|
if (!hypercall_pg)
|
||||||
|
return (u64)ULLONG_MAX;
|
||||||
|
|
||||||
|
__asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8");
|
||||||
|
__asm__ __volatile__("call *%3" : "=a" (hv_status) :
|
||||||
|
"c" (control), "d" (input_address),
|
||||||
|
"m" (hypercall_pg));
|
||||||
|
|
||||||
|
return hv_status;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
u32 control_hi = control >> 32;
|
||||||
|
u32 control_lo = control & 0xFFFFFFFF;
|
||||||
|
u32 hv_status_hi = 1;
|
||||||
|
u32 hv_status_lo = 1;
|
||||||
|
u32 input_address_hi = input_address >> 32;
|
||||||
|
u32 input_address_lo = input_address & 0xFFFFFFFF;
|
||||||
|
u32 output_address_hi = output_address >> 32;
|
||||||
|
u32 output_address_lo = output_address & 0xFFFFFFFF;
|
||||||
|
|
||||||
|
if (!hypercall_pg)
|
||||||
|
return (u64)ULLONG_MAX;
|
||||||
|
|
||||||
|
__asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi),
|
||||||
|
"=a"(hv_status_lo) : "d" (control_hi),
|
||||||
|
"a" (control_lo), "b" (input_address_hi),
|
||||||
|
"c" (input_address_lo), "D"(output_address_hi),
|
||||||
|
"S"(output_address_lo), "m" (hypercall_pg));
|
||||||
|
|
||||||
|
return hv_status_lo | ((u64)hv_status_hi << 32);
|
||||||
|
#endif /* !x86_64 */
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(hv_do_hypercall);
|
||||||
|
|
||||||
|
void hyperv_report_panic(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
static bool panic_reported;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We prefer to report panic on 'die' chain as we have proper
|
||||||
|
* registers to report, but if we miss it (e.g. on BUG()) we need
|
||||||
|
* to report it on 'panic'.
|
||||||
|
*/
|
||||||
|
if (panic_reported)
|
||||||
|
return;
|
||||||
|
panic_reported = true;
|
||||||
|
|
||||||
|
wrmsrl(HV_X64_MSR_CRASH_P0, regs->ip);
|
||||||
|
wrmsrl(HV_X64_MSR_CRASH_P1, regs->ax);
|
||||||
|
wrmsrl(HV_X64_MSR_CRASH_P2, regs->bx);
|
||||||
|
wrmsrl(HV_X64_MSR_CRASH_P3, regs->cx);
|
||||||
|
wrmsrl(HV_X64_MSR_CRASH_P4, regs->dx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let Hyper-V know there is crash data available
|
||||||
|
*/
|
||||||
|
wrmsrl(HV_X64_MSR_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(hyperv_report_panic);
|
||||||
|
|
||||||
|
bool hv_is_hypercall_page_setup(void)
|
||||||
|
{
|
||||||
|
union hv_x64_msr_hypercall_contents hypercall_msr;
|
||||||
|
|
||||||
|
/* Check if the hypercall page is setup */
|
||||||
|
hypercall_msr.as_uint64 = 0;
|
||||||
|
rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
|
||||||
|
|
||||||
|
if (!hypercall_msr.enable)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(hv_is_hypercall_page_setup);
|
||||||
@@ -3,8 +3,28 @@
|
|||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/clocksource.h>
|
||||||
#include <asm/hyperv.h>
|
#include <asm/hyperv.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
|
||||||
|
* is set by CPUID(HVCPUID_VERSION_FEATURES).
|
||||||
|
*/
|
||||||
|
enum hv_cpuid_function {
|
||||||
|
HVCPUID_VERSION_FEATURES = 0x00000001,
|
||||||
|
HVCPUID_VENDOR_MAXFUNCTION = 0x40000000,
|
||||||
|
HVCPUID_INTERFACE = 0x40000001,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The remaining functions depend on the value of
|
||||||
|
* HVCPUID_INTERFACE
|
||||||
|
*/
|
||||||
|
HVCPUID_VERSION = 0x40000002,
|
||||||
|
HVCPUID_FEATURES = 0x40000003,
|
||||||
|
HVCPUID_ENLIGHTENMENT_INFO = 0x40000004,
|
||||||
|
HVCPUID_IMPLEMENTATION_LIMITS = 0x40000005,
|
||||||
|
};
|
||||||
|
|
||||||
struct ms_hyperv_info {
|
struct ms_hyperv_info {
|
||||||
u32 features;
|
u32 features;
|
||||||
u32 misc_features;
|
u32 misc_features;
|
||||||
@@ -13,6 +33,128 @@ struct ms_hyperv_info {
|
|||||||
|
|
||||||
extern struct ms_hyperv_info ms_hyperv;
|
extern struct ms_hyperv_info ms_hyperv;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Declare the MSR used to setup pages used to communicate with the hypervisor.
|
||||||
|
*/
|
||||||
|
union hv_x64_msr_hypercall_contents {
|
||||||
|
u64 as_uint64;
|
||||||
|
struct {
|
||||||
|
u64 enable:1;
|
||||||
|
u64 reserved:11;
|
||||||
|
u64 guest_physical_address:52;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TSC page layout.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct ms_hyperv_tsc_page {
|
||||||
|
volatile u32 tsc_sequence;
|
||||||
|
u32 reserved1;
|
||||||
|
volatile u64 tsc_scale;
|
||||||
|
volatile s64 tsc_offset;
|
||||||
|
u64 reserved2[509];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The guest OS needs to register the guest ID with the hypervisor.
|
||||||
|
* The guest ID is a 64 bit entity and the structure of this ID is
|
||||||
|
* specified in the Hyper-V specification:
|
||||||
|
*
|
||||||
|
* msdn.microsoft.com/en-us/library/windows/hardware/ff542653%28v=vs.85%29.aspx
|
||||||
|
*
|
||||||
|
* While the current guideline does not specify how Linux guest ID(s)
|
||||||
|
* need to be generated, our plan is to publish the guidelines for
|
||||||
|
* Linux and other guest operating systems that currently are hosted
|
||||||
|
* on Hyper-V. The implementation here conforms to this yet
|
||||||
|
* unpublished guidelines.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Bit(s)
|
||||||
|
* 63 - Indicates if the OS is Open Source or not; 1 is Open Source
|
||||||
|
* 62:56 - Os Type; Linux is 0x100
|
||||||
|
* 55:48 - Distro specific identification
|
||||||
|
* 47:16 - Linux kernel version number
|
||||||
|
* 15:0 - Distro specific identification
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HV_LINUX_VENDOR_ID 0x8100
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate the guest ID based on the guideline described above.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline __u64 generate_guest_id(__u64 d_info1, __u64 kernel_version,
|
||||||
|
__u64 d_info2)
|
||||||
|
{
|
||||||
|
__u64 guest_id = 0;
|
||||||
|
|
||||||
|
guest_id = (((__u64)HV_LINUX_VENDOR_ID) << 48);
|
||||||
|
guest_id |= (d_info1 << 48);
|
||||||
|
guest_id |= (kernel_version << 16);
|
||||||
|
guest_id |= d_info2;
|
||||||
|
|
||||||
|
return guest_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Free the message slot and signal end-of-message if required */
|
||||||
|
static inline void vmbus_signal_eom(struct hv_message *msg, u32 old_msg_type)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* On crash we're reading some other CPU's message page and we need
|
||||||
|
* to be careful: this other CPU may already had cleared the header
|
||||||
|
* and the host may already had delivered some other message there.
|
||||||
|
* In case we blindly write msg->header.message_type we're going
|
||||||
|
* to lose it. We can still lose a message of the same type but
|
||||||
|
* we count on the fact that there can only be one
|
||||||
|
* CHANNELMSG_UNLOAD_RESPONSE and we don't care about other messages
|
||||||
|
* on crash.
|
||||||
|
*/
|
||||||
|
if (cmpxchg(&msg->header.message_type, old_msg_type,
|
||||||
|
HVMSG_NONE) != old_msg_type)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the write to MessageType (ie set to
|
||||||
|
* HVMSG_NONE) happens before we read the
|
||||||
|
* MessagePending and EOMing. Otherwise, the EOMing
|
||||||
|
* will not deliver any more messages since there is
|
||||||
|
* no empty slot
|
||||||
|
*/
|
||||||
|
mb();
|
||||||
|
|
||||||
|
if (msg->header.message_flags.msg_pending) {
|
||||||
|
/*
|
||||||
|
* This will cause message queue rescan to
|
||||||
|
* possibly deliver another msg from the
|
||||||
|
* hypervisor
|
||||||
|
*/
|
||||||
|
wrmsrl(HV_X64_MSR_EOM, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define hv_get_current_tick(tick) rdmsrl(HV_X64_MSR_TIME_REF_COUNT, tick)
|
||||||
|
#define hv_init_timer(timer, tick) wrmsrl(timer, tick)
|
||||||
|
#define hv_init_timer_config(config, val) wrmsrl(config, val)
|
||||||
|
|
||||||
|
#define hv_get_simp(val) rdmsrl(HV_X64_MSR_SIMP, val)
|
||||||
|
#define hv_set_simp(val) wrmsrl(HV_X64_MSR_SIMP, val)
|
||||||
|
|
||||||
|
#define hv_get_siefp(val) rdmsrl(HV_X64_MSR_SIEFP, val)
|
||||||
|
#define hv_set_siefp(val) wrmsrl(HV_X64_MSR_SIEFP, val)
|
||||||
|
|
||||||
|
#define hv_get_synic_state(val) rdmsrl(HV_X64_MSR_SCONTROL, val)
|
||||||
|
#define hv_set_synic_state(val) wrmsrl(HV_X64_MSR_SCONTROL, val)
|
||||||
|
|
||||||
|
#define hv_get_vp_index(index) rdmsrl(HV_X64_MSR_VP_INDEX, index)
|
||||||
|
|
||||||
|
#define hv_get_synint_state(int_num, val) rdmsrl(int_num, val)
|
||||||
|
#define hv_set_synint_state(int_num, val) wrmsrl(int_num, val)
|
||||||
|
|
||||||
void hyperv_callback_vector(void);
|
void hyperv_callback_vector(void);
|
||||||
#ifdef CONFIG_TRACING
|
#ifdef CONFIG_TRACING
|
||||||
#define trace_hyperv_callback_vector hyperv_callback_vector
|
#define trace_hyperv_callback_vector hyperv_callback_vector
|
||||||
@@ -25,4 +167,13 @@ void hv_setup_kexec_handler(void (*handler)(void));
|
|||||||
void hv_remove_kexec_handler(void);
|
void hv_remove_kexec_handler(void);
|
||||||
void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
|
void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
|
||||||
void hv_remove_crash_handler(void);
|
void hv_remove_crash_handler(void);
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_HYPERV)
|
||||||
|
extern struct clocksource *hyperv_cs;
|
||||||
|
|
||||||
|
void hyperv_init(void);
|
||||||
|
void hyperv_report_panic(struct pt_regs *regs);
|
||||||
|
bool hv_is_hypercall_page_setup(void);
|
||||||
|
void hyperv_cleanup(void);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -73,6 +73,9 @@
|
|||||||
*/
|
*/
|
||||||
#define HV_X64_MSR_STAT_PAGES_AVAILABLE (1 << 8)
|
#define HV_X64_MSR_STAT_PAGES_AVAILABLE (1 << 8)
|
||||||
|
|
||||||
|
/* Crash MSR available */
|
||||||
|
#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE (1 << 10)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Feature identification: EBX indicates which flags were specified at
|
* Feature identification: EBX indicates which flags were specified at
|
||||||
* partition creation. The format is the same as the partition creation
|
* partition creation. The format is the same as the partition creation
|
||||||
@@ -144,6 +147,11 @@
|
|||||||
*/
|
*/
|
||||||
#define HV_X64_RELAXED_TIMING_RECOMMENDED (1 << 5)
|
#define HV_X64_RELAXED_TIMING_RECOMMENDED (1 << 5)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Crash notification flag.
|
||||||
|
*/
|
||||||
|
#define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63)
|
||||||
|
|
||||||
/* MSR used to identify the guest OS. */
|
/* MSR used to identify the guest OS. */
|
||||||
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
|
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
|
||||||
|
|
||||||
|
|||||||
@@ -133,26 +133,6 @@ static uint32_t __init ms_hyperv_platform(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u64 read_hv_clock(struct clocksource *arg)
|
|
||||||
{
|
|
||||||
u64 current_tick;
|
|
||||||
/*
|
|
||||||
* Read the partition counter to get the current tick count. This count
|
|
||||||
* is set to 0 when the partition is created and is incremented in
|
|
||||||
* 100 nanosecond units.
|
|
||||||
*/
|
|
||||||
rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
|
|
||||||
return current_tick;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct clocksource hyperv_cs = {
|
|
||||||
.name = "hyperv_clocksource",
|
|
||||||
.rating = 400, /* use this when running on Hyperv*/
|
|
||||||
.read = read_hv_clock,
|
|
||||||
.mask = CLOCKSOURCE_MASK(64),
|
|
||||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
|
||||||
};
|
|
||||||
|
|
||||||
static unsigned char hv_get_nmi_reason(void)
|
static unsigned char hv_get_nmi_reason(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -180,6 +160,11 @@ static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs)
|
|||||||
|
|
||||||
static void __init ms_hyperv_init_platform(void)
|
static void __init ms_hyperv_init_platform(void)
|
||||||
{
|
{
|
||||||
|
int hv_host_info_eax;
|
||||||
|
int hv_host_info_ebx;
|
||||||
|
int hv_host_info_ecx;
|
||||||
|
int hv_host_info_edx;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extract the features and hints
|
* Extract the features and hints
|
||||||
*/
|
*/
|
||||||
@@ -190,6 +175,21 @@ static void __init ms_hyperv_init_platform(void)
|
|||||||
pr_info("HyperV: features 0x%x, hints 0x%x\n",
|
pr_info("HyperV: features 0x%x, hints 0x%x\n",
|
||||||
ms_hyperv.features, ms_hyperv.hints);
|
ms_hyperv.features, ms_hyperv.hints);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract host information.
|
||||||
|
*/
|
||||||
|
if (cpuid_eax(HVCPUID_VENDOR_MAXFUNCTION) >= HVCPUID_VERSION) {
|
||||||
|
hv_host_info_eax = cpuid_eax(HVCPUID_VERSION);
|
||||||
|
hv_host_info_ebx = cpuid_ebx(HVCPUID_VERSION);
|
||||||
|
hv_host_info_ecx = cpuid_ecx(HVCPUID_VERSION);
|
||||||
|
hv_host_info_edx = cpuid_edx(HVCPUID_VERSION);
|
||||||
|
|
||||||
|
pr_info("Hyper-V Host Build:%d-%d.%d-%d-%d.%d\n",
|
||||||
|
hv_host_info_eax, hv_host_info_ebx >> 16,
|
||||||
|
hv_host_info_ebx & 0xFFFF, hv_host_info_ecx,
|
||||||
|
hv_host_info_edx >> 24, hv_host_info_edx & 0xFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
if (ms_hyperv.features & HV_X64_MSR_APIC_FREQUENCY_AVAILABLE) {
|
if (ms_hyperv.features & HV_X64_MSR_APIC_FREQUENCY_AVAILABLE) {
|
||||||
/*
|
/*
|
||||||
@@ -208,9 +208,6 @@ static void __init ms_hyperv_init_platform(void)
|
|||||||
"hv_nmi_unknown");
|
"hv_nmi_unknown");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
|
|
||||||
clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
no_timer_check = 1;
|
no_timer_check = 1;
|
||||||
#endif
|
#endif
|
||||||
@@ -227,6 +224,13 @@ static void __init ms_hyperv_init_platform(void)
|
|||||||
*/
|
*/
|
||||||
if (efi_enabled(EFI_BOOT))
|
if (efi_enabled(EFI_BOOT))
|
||||||
x86_platform.get_nmi_reason = hv_get_nmi_reason;
|
x86_platform.get_nmi_reason = hv_get_nmi_reason;
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_HYPERV)
|
||||||
|
/*
|
||||||
|
* Setup the hook to get control post apic initialization.
|
||||||
|
*/
|
||||||
|
x86_platform.apic_post_init = hyperv_init;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
|
const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
|
||||||
|
|||||||
@@ -42,8 +42,20 @@ static struct resource goldfish_pdev_bus_resources[] = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool goldfish_enable __initdata;
|
||||||
|
|
||||||
|
static int __init goldfish_setup(char *str)
|
||||||
|
{
|
||||||
|
goldfish_enable = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
__setup("goldfish", goldfish_setup);
|
||||||
|
|
||||||
static int __init goldfish_init(void)
|
static int __init goldfish_init(void)
|
||||||
{
|
{
|
||||||
|
if (!goldfish_enable)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
platform_device_register_simple("goldfish_pdev_bus", -1,
|
platform_device_register_simple("goldfish_pdev_bus", -1,
|
||||||
goldfish_pdev_bus_resources, 2);
|
goldfish_pdev_bus_resources, 2);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user