hyperv-fixes for v6.6-rc6
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEIbPD0id6easf0xsudhRwX5BBoF4FAmUk4fcTHHdlaS5saXVA a2VybmVsLm9yZwAKCRB2FHBfkEGgXhhqCACWsBYTB0EJ3oMJnzfnHeuN418ZDx/O AL0k0O5MT6roEFmvGUhzJ/jsoxL+W+Wj3aFwzReyOSQpgjTTF/Ja26LPvxRzDxKi sZPojnR2ykW31l7y+eh1p9qSM/aYvTMDP5zO7L1fBnWMAGMv8w8RezpCJ7bh4BgA FTMZZrvKYVT9hCGkYqKUZGBtDTPZ56WE+MCiRxTWQvF+4QKaIff0tpno8V7203bE D/b4+Ouh19RXFTC5dUq/0JtAdV2AadrPHnScUupc8Hk/MMFiU5CzvH4bAqiwXBcU YqqlD3kZbIqqbKE93+03jvyrRDvDGlq+rpA3KMk5MBAfrkM4DytpWvMs =SVq1 -----END PGP SIGNATURE----- Merge tag 'hyperv-fixes-signed-20231009' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux Pull hyperv fixes from Wei Liu: - fixes for Hyper-V VTL code (Saurabh Sengar and Olaf Hering) - fix hv_kvp_daemon to support keyfile based connection profile (Shradha Gupta) * tag 'hyperv-fixes-signed-20231009' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: hv/hv_kvp_daemon:Support for keyfile based connection profile hyperv: reduce size of ms_hyperv_info x86/hyperv: Add common print prefix "Hyper-V" in hv_init x86/hyperv: Remove hv_vtl_early_init initcall x86/hyperv: Restrict get_vtl to only VTL platforms
This commit is contained in:
commit
b711538a40
|
@ -7,6 +7,8 @@
|
|||
* Author : K. Y. Srinivasan <kys@microsoft.com>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "Hyper-V: " fmt
|
||||
|
||||
#include <linux/efi.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/bitfield.h>
|
||||
|
@ -191,7 +193,7 @@ void set_hv_tscchange_cb(void (*cb)(void))
|
|||
struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1};
|
||||
|
||||
if (!hv_reenlightenment_available()) {
|
||||
pr_warn("Hyper-V: reenlightenment support is unavailable\n");
|
||||
pr_warn("reenlightenment support is unavailable\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -394,6 +396,7 @@ static void __init hv_get_partition_id(void)
|
|||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_HYPERV_VTL_MODE)
|
||||
static u8 __init get_vtl(void)
|
||||
{
|
||||
u64 control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_REGISTERS;
|
||||
|
@ -416,13 +419,16 @@ static u8 __init get_vtl(void)
|
|||
if (hv_result_success(ret)) {
|
||||
ret = output->as64.low & HV_X64_VTL_MASK;
|
||||
} else {
|
||||
pr_err("Failed to get VTL(%lld) and set VTL to zero by default.\n", ret);
|
||||
ret = 0;
|
||||
pr_err("Failed to get VTL(error: %lld) exiting...\n", ret);
|
||||
BUG();
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static inline u8 get_vtl(void) { return 0; }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function is to be invoked early in the boot sequence after the
|
||||
|
@ -564,7 +570,7 @@ skip_hypercall_pg_init:
|
|||
if (cpu_feature_enabled(X86_FEATURE_IBT) &&
|
||||
*(u32 *)hv_hypercall_pg != gen_endbr()) {
|
||||
setup_clear_cpu_cap(X86_FEATURE_IBT);
|
||||
pr_warn("Hyper-V: Disabling IBT because of Hyper-V bug\n");
|
||||
pr_warn("Disabling IBT because of Hyper-V bug\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -604,8 +610,10 @@ skip_hypercall_pg_init:
|
|||
hv_query_ext_cap(0);
|
||||
|
||||
/* Find the VTL */
|
||||
if (!ms_hyperv.paravisor_present && hv_isolation_type_snp())
|
||||
ms_hyperv.vtl = get_vtl();
|
||||
ms_hyperv.vtl = get_vtl();
|
||||
|
||||
if (ms_hyperv.vtl > 0) /* non default VTL */
|
||||
hv_vtl_early_init();
|
||||
|
||||
return;
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@ static int hv_vtl_wakeup_secondary_cpu(int apicid, unsigned long start_eip)
|
|||
return hv_vtl_bringup_vcpu(vp_id, start_eip);
|
||||
}
|
||||
|
||||
static int __init hv_vtl_early_init(void)
|
||||
int __init hv_vtl_early_init(void)
|
||||
{
|
||||
/*
|
||||
* `boot_cpu_has` returns the runtime feature support,
|
||||
|
@ -230,4 +230,3 @@ static int __init hv_vtl_early_init(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
early_initcall(hv_vtl_early_init);
|
||||
|
|
|
@ -340,8 +340,10 @@ static inline u64 hv_get_non_nested_register(unsigned int reg) { return 0; }
|
|||
|
||||
#ifdef CONFIG_HYPERV_VTL_MODE
|
||||
void __init hv_vtl_init_platform(void);
|
||||
int __init hv_vtl_early_init(void);
|
||||
#else
|
||||
static inline void __init hv_vtl_init_platform(void) {}
|
||||
static inline int __init hv_vtl_early_init(void) { return 0; }
|
||||
#endif
|
||||
|
||||
#include <asm-generic/mshyperv.h>
|
||||
|
|
|
@ -36,6 +36,7 @@ struct ms_hyperv_info {
|
|||
u32 nested_features;
|
||||
u32 max_vp_index;
|
||||
u32 max_lp_index;
|
||||
u8 vtl;
|
||||
union {
|
||||
u32 isolation_config_a;
|
||||
struct {
|
||||
|
@ -54,7 +55,6 @@ struct ms_hyperv_info {
|
|||
};
|
||||
};
|
||||
u64 shared_gpa_boundary;
|
||||
u8 vtl;
|
||||
};
|
||||
extern struct ms_hyperv_info ms_hyperv;
|
||||
extern bool hv_nested;
|
||||
|
|
|
@ -1171,12 +1171,79 @@ static int process_ip_string(FILE *f, char *ip_string, int type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only IPv4 subnet strings needs to be converted to plen
|
||||
* For IPv6 the subnet is already privided in plen format
|
||||
*/
|
||||
static int kvp_subnet_to_plen(char *subnet_addr_str)
|
||||
{
|
||||
int plen = 0;
|
||||
struct in_addr subnet_addr4;
|
||||
|
||||
/*
|
||||
* Convert subnet address to binary representation
|
||||
*/
|
||||
if (inet_pton(AF_INET, subnet_addr_str, &subnet_addr4) == 1) {
|
||||
uint32_t subnet_mask = ntohl(subnet_addr4.s_addr);
|
||||
|
||||
while (subnet_mask & 0x80000000) {
|
||||
plen++;
|
||||
subnet_mask <<= 1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return plen;
|
||||
}
|
||||
|
||||
static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet,
|
||||
int is_ipv6)
|
||||
{
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
char subnet_addr[INET6_ADDRSTRLEN];
|
||||
int error, i = 0;
|
||||
int ip_offset = 0, subnet_offset = 0;
|
||||
int plen;
|
||||
|
||||
memset(addr, 0, sizeof(addr));
|
||||
memset(subnet_addr, 0, sizeof(subnet_addr));
|
||||
|
||||
while (parse_ip_val_buffer(ip_string, &ip_offset, addr,
|
||||
(MAX_IP_ADDR_SIZE * 2)) &&
|
||||
parse_ip_val_buffer(subnet,
|
||||
&subnet_offset,
|
||||
subnet_addr,
|
||||
(MAX_IP_ADDR_SIZE *
|
||||
2))) {
|
||||
if (!is_ipv6)
|
||||
plen = kvp_subnet_to_plen((char *)subnet_addr);
|
||||
else
|
||||
plen = atoi(subnet_addr);
|
||||
|
||||
if (plen < 0)
|
||||
return plen;
|
||||
|
||||
error = fprintf(f, "address%d=%s/%d\n", ++i, (char *)addr,
|
||||
plen);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
memset(addr, 0, sizeof(addr));
|
||||
memset(subnet_addr, 0, sizeof(subnet_addr));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
{
|
||||
int error = 0;
|
||||
char if_file[PATH_MAX];
|
||||
FILE *file;
|
||||
char if_filename[PATH_MAX];
|
||||
char nm_filename[PATH_MAX];
|
||||
FILE *ifcfg_file, *nmfile;
|
||||
char cmd[PATH_MAX];
|
||||
int is_ipv6 = 0;
|
||||
char *mac_addr;
|
||||
int str_len;
|
||||
|
||||
|
@ -1197,7 +1264,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
|||
* in a given distro to configure the interface and so are free
|
||||
* ignore information that may not be relevant.
|
||||
*
|
||||
* Here is the format of the ip configuration file:
|
||||
* Here is the ifcfg format of the ip configuration file:
|
||||
*
|
||||
* HWADDR=macaddr
|
||||
* DEVICE=interface name
|
||||
|
@ -1220,6 +1287,32 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
|||
* tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as
|
||||
* IPV6NETMASK.
|
||||
*
|
||||
* Here is the keyfile format of the ip configuration file:
|
||||
*
|
||||
* [ethernet]
|
||||
* mac-address=macaddr
|
||||
* [connection]
|
||||
* interface-name=interface name
|
||||
*
|
||||
* [ipv4]
|
||||
* method=<protocol> (where <protocol> is "auto" if DHCP is configured
|
||||
* or "manual" if no boot-time protocol should be used)
|
||||
*
|
||||
* address1=ipaddr1/plen
|
||||
* address2=ipaddr2/plen
|
||||
*
|
||||
* gateway=gateway1;gateway2
|
||||
*
|
||||
* dns=dns1;dns2
|
||||
*
|
||||
* [ipv6]
|
||||
* address1=ipaddr1/plen
|
||||
* address2=ipaddr2/plen
|
||||
*
|
||||
* gateway=gateway1;gateway2
|
||||
*
|
||||
* dns=dns1;dns2
|
||||
*
|
||||
* The host can specify multiple ipv4 and ipv6 addresses to be
|
||||
* configured for the interface. Furthermore, the configuration
|
||||
* needs to be persistent. A subsequent GET call on the interface
|
||||
|
@ -1227,14 +1320,29 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
|||
* call.
|
||||
*/
|
||||
|
||||
snprintf(if_file, sizeof(if_file), "%s%s%s", KVP_CONFIG_LOC,
|
||||
"/ifcfg-", if_name);
|
||||
/*
|
||||
* We are populating both ifcfg and nmconnection files
|
||||
*/
|
||||
snprintf(if_filename, sizeof(if_filename), "%s%s%s", KVP_CONFIG_LOC,
|
||||
"/ifcfg-", if_name);
|
||||
|
||||
file = fopen(if_file, "w");
|
||||
ifcfg_file = fopen(if_filename, "w");
|
||||
|
||||
if (file == NULL) {
|
||||
if (!ifcfg_file) {
|
||||
syslog(LOG_ERR, "Failed to open config file; error: %d %s",
|
||||
errno, strerror(errno));
|
||||
errno, strerror(errno));
|
||||
return HV_E_FAIL;
|
||||
}
|
||||
|
||||
snprintf(nm_filename, sizeof(nm_filename), "%s%s%s%s", KVP_CONFIG_LOC,
|
||||
"/", if_name, ".nmconnection");
|
||||
|
||||
nmfile = fopen(nm_filename, "w");
|
||||
|
||||
if (!nmfile) {
|
||||
syslog(LOG_ERR, "Failed to open config file; error: %d %s",
|
||||
errno, strerror(errno));
|
||||
fclose(ifcfg_file);
|
||||
return HV_E_FAIL;
|
||||
}
|
||||
|
||||
|
@ -1248,14 +1356,31 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
|||
goto setval_error;
|
||||
}
|
||||
|
||||
error = kvp_write_file(file, "HWADDR", "", mac_addr);
|
||||
free(mac_addr);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
error = kvp_write_file(ifcfg_file, "HWADDR", "", mac_addr);
|
||||
if (error < 0)
|
||||
goto setmac_error;
|
||||
|
||||
error = kvp_write_file(file, "DEVICE", "", if_name);
|
||||
error = kvp_write_file(ifcfg_file, "DEVICE", "", if_name);
|
||||
if (error < 0)
|
||||
goto setmac_error;
|
||||
|
||||
error = fprintf(nmfile, "\n[connection]\n");
|
||||
if (error < 0)
|
||||
goto setmac_error;
|
||||
|
||||
error = kvp_write_file(nmfile, "interface-name", "", if_name);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
goto setmac_error;
|
||||
|
||||
error = fprintf(nmfile, "\n[ethernet]\n");
|
||||
if (error < 0)
|
||||
goto setmac_error;
|
||||
|
||||
error = kvp_write_file(nmfile, "mac-address", "", mac_addr);
|
||||
if (error)
|
||||
goto setmac_error;
|
||||
|
||||
free(mac_addr);
|
||||
|
||||
/*
|
||||
* The dhcp_enabled flag is only for IPv4. In the case the host only
|
||||
|
@ -1263,47 +1388,91 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
|||
* proceed to parse and pass the IPv6 information to the
|
||||
* disto-specific script hv_set_ifconfig.
|
||||
*/
|
||||
|
||||
/*
|
||||
* First populate the ifcfg file format
|
||||
*/
|
||||
if (new_val->dhcp_enabled) {
|
||||
error = kvp_write_file(file, "BOOTPROTO", "", "dhcp");
|
||||
error = kvp_write_file(ifcfg_file, "BOOTPROTO", "", "dhcp");
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
} else {
|
||||
error = kvp_write_file(file, "BOOTPROTO", "", "none");
|
||||
error = kvp_write_file(ifcfg_file, "BOOTPROTO", "", "none");
|
||||
if (error)
|
||||
goto setval_error;
|
||||
}
|
||||
|
||||
error = process_ip_string(ifcfg_file, (char *)new_val->ip_addr,
|
||||
IPADDR);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
error = process_ip_string(ifcfg_file, (char *)new_val->sub_net,
|
||||
NETMASK);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
error = process_ip_string(ifcfg_file, (char *)new_val->gate_way,
|
||||
GATEWAY);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
error = process_ip_string(ifcfg_file, (char *)new_val->dns_addr, DNS);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
if (new_val->addr_family == ADDR_FAMILY_IPV6) {
|
||||
error = fprintf(nmfile, "\n[ipv6]\n");
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
is_ipv6 = 1;
|
||||
} else {
|
||||
error = fprintf(nmfile, "\n[ipv4]\n");
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we populate the keyfile format
|
||||
*/
|
||||
|
||||
if (new_val->dhcp_enabled) {
|
||||
error = kvp_write_file(nmfile, "method", "", "auto");
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
} else {
|
||||
error = kvp_write_file(nmfile, "method", "", "manual");
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the configuration for ipaddress, netmask, gateway and
|
||||
* name servers.
|
||||
* name services
|
||||
*/
|
||||
|
||||
error = process_ip_string(file, (char *)new_val->ip_addr, IPADDR);
|
||||
if (error)
|
||||
error = process_ip_string_nm(nmfile, (char *)new_val->ip_addr,
|
||||
(char *)new_val->sub_net, is_ipv6);
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
|
||||
error = process_ip_string(file, (char *)new_val->sub_net, NETMASK);
|
||||
if (error)
|
||||
error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
|
||||
error = process_ip_string(file, (char *)new_val->gate_way, GATEWAY);
|
||||
if (error)
|
||||
error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
|
||||
error = process_ip_string(file, (char *)new_val->dns_addr, DNS);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
fclose(file);
|
||||
fclose(nmfile);
|
||||
fclose(ifcfg_file);
|
||||
|
||||
/*
|
||||
* Now that we have populated the configuration file,
|
||||
* invoke the external script to do its magic.
|
||||
*/
|
||||
|
||||
str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s",
|
||||
"hv_set_ifconfig", if_file);
|
||||
str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s %s",
|
||||
"hv_set_ifconfig", if_filename, nm_filename);
|
||||
/*
|
||||
* This is a little overcautious, but it's necessary to suppress some
|
||||
* false warnings from gcc 8.0.1.
|
||||
|
@ -1316,14 +1485,16 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
|||
|
||||
if (system(cmd)) {
|
||||
syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s",
|
||||
cmd, errno, strerror(errno));
|
||||
cmd, errno, strerror(errno));
|
||||
return HV_E_FAIL;
|
||||
}
|
||||
return 0;
|
||||
|
||||
setmac_error:
|
||||
free(mac_addr);
|
||||
setval_error:
|
||||
syslog(LOG_ERR, "Failed to write config file");
|
||||
fclose(file);
|
||||
fclose(ifcfg_file);
|
||||
fclose(nmfile);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
#
|
||||
# This example script is based on a RHEL environment.
|
||||
#
|
||||
# Here is the format of the ip configuration file:
|
||||
# Here is the ifcfg format of the ip configuration file:
|
||||
#
|
||||
# HWADDR=macaddr
|
||||
# DEVICE=interface name
|
||||
# BOOTPROTO=<protocol> (where <protocol> is "dhcp" if DHCP is configured
|
||||
# or "none" if no boot-time protocol should be used)
|
||||
# or "none" if no boot-time protocol should be used)
|
||||
#
|
||||
# IPADDR0=ipaddr1
|
||||
# IPADDR1=ipaddr2
|
||||
|
@ -41,6 +41,32 @@
|
|||
# tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as
|
||||
# IPV6NETMASK.
|
||||
#
|
||||
# Here is the keyfile format of the ip configuration file:
|
||||
#
|
||||
# [ethernet]
|
||||
# mac-address=macaddr
|
||||
# [connection]
|
||||
# interface-name=interface name
|
||||
#
|
||||
# [ipv4]
|
||||
# method=<protocol> (where <protocol> is "auto" if DHCP is configured
|
||||
# or "manual" if no boot-time protocol should be used)
|
||||
#
|
||||
# address1=ipaddr1/plen
|
||||
# address=ipaddr2/plen
|
||||
#
|
||||
# gateway=gateway1;gateway2
|
||||
#
|
||||
# dns=dns1;
|
||||
#
|
||||
# [ipv6]
|
||||
# address1=ipaddr1/plen
|
||||
# address2=ipaddr1/plen
|
||||
#
|
||||
# gateway=gateway1;gateway2
|
||||
#
|
||||
# dns=dns1;dns2
|
||||
#
|
||||
# The host can specify multiple ipv4 and ipv6 addresses to be
|
||||
# configured for the interface. Furthermore, the configuration
|
||||
# needs to be persistent. A subsequent GET call on the interface
|
||||
|
@ -48,18 +74,19 @@
|
|||
# call.
|
||||
#
|
||||
|
||||
|
||||
|
||||
echo "IPV6INIT=yes" >> $1
|
||||
echo "NM_CONTROLLED=no" >> $1
|
||||
echo "PEERDNS=yes" >> $1
|
||||
echo "ONBOOT=yes" >> $1
|
||||
|
||||
|
||||
cp $1 /etc/sysconfig/network-scripts/
|
||||
|
||||
chmod 600 $2
|
||||
interface=$(echo $2 | awk -F - '{ print $2 }')
|
||||
filename="${2##*/}"
|
||||
|
||||
sed '/\[connection\]/a autoconnect=true' $2 > /etc/NetworkManager/system-connections/${filename}
|
||||
|
||||
interface=$(echo $1 | awk -F - '{ print $2 }')
|
||||
|
||||
/sbin/ifdown $interface 2>/dev/null
|
||||
/sbin/ifup $interface 2>/dev/null
|
||||
|
|
Loading…
Reference in New Issue